public override void ProcessCommand()
		{
            logger.Info("Get AniDB episode info: {0}", EpisodeID);

			
			try
			{
                // we don't use this command to update episode info
                // we actually use it to update the cross ref info instead
                // and we only use it for the "Other Episodes" section of the FILE command
                // because that field doesn't tell you what anime it belongs to

                CrossRef_File_EpisodeRepository repCrossRefs = new CrossRef_File_EpisodeRepository();
                List<CrossRef_File_Episode> xrefs = repCrossRefs.GetByEpisodeID(EpisodeID);
                if (xrefs.Count == 0) return;

                Raw_AniDB_Episode epInfo = JMMService.AnidbProcessor.GetEpisodeInfo(EpisodeID);
                if (epInfo != null)
				{
                    AnimeSeriesRepository repSeries = new AnimeSeriesRepository();

                    foreach (CrossRef_File_Episode xref in xrefs)
                    {
                        int oldAnimeID = xref.AnimeID;
                        xref.AnimeID = epInfo.AnimeID;
                        repCrossRefs.Save(xref);


                        AnimeSeries ser = repSeries.GetByAnimeID(oldAnimeID);
                        if (ser != null)
                            ser.UpdateStats(true, true, true);
                        StatsCache.Instance.UpdateUsingAnime(oldAnimeID);

                        ser = repSeries.GetByAnimeID(epInfo.AnimeID);
                        if (ser != null)
                            ser.UpdateStats(true, true, true);
                        StatsCache.Instance.UpdateUsingAnime(epInfo.AnimeID);
                    }
				}
				
			}
			catch (Exception ex)
			{
                logger.Error("Error processing CommandRequest_GetEpisode: {0} - {1}", EpisodeID, ex.ToString());
				return;
			}
		}
		public override void ProcessCommand()
		{
			
			try
			{
				CrossRef_File_EpisodeRepository repVids = new CrossRef_File_EpisodeRepository();
				CrossRef_File_Episode xref = repVids.GetByID(CrossRef_File_EpisodeID);
				if (xref == null) return;

                JMMServer.Providers.Azure.AzureWebAPI.Send_CrossRefFileEpisode(xref);
			}
			catch (Exception ex)
			{
				logger.Error("Error processing CommandRequest_WebCacheSendXRefFileEpisode: {0} - {1}", CrossRef_File_EpisodeID, ex.ToString());
				return;
			}
		}
Example #3
0
        public string RemoveAssociationOnFile(int videoLocalID, int aniDBEpisodeID)
        {
            try
            {
                VideoLocalRepository repVids = new VideoLocalRepository();
                CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository();

                VideoLocal vid = repVids.GetByID(videoLocalID);
                if (vid == null)
                    return "Could not find video record";

                int? animeSeriesID = null;
                foreach (AnimeEpisode ep in vid.GetAnimeEpisodes())
                {
                    if (ep.AniDB_EpisodeID != aniDBEpisodeID) continue;

                    animeSeriesID = ep.AnimeSeriesID;
                    CrossRef_File_Episode xref = repXRefs.GetByHashAndEpisodeID(vid.Hash, ep.AniDB_EpisodeID);
                    if (xref != null)
                    {
                        if (xref.CrossRefSource == (int)CrossRefSource.AniDB)
                            return "Cannot remove associations created from AniDB data";

                        // delete cross ref from web cache
                        CommandRequest_WebCacheDeleteXRefFileEpisode cr = new CommandRequest_WebCacheDeleteXRefFileEpisode(vid.Hash, ep.AniDB_EpisodeID);
                        cr.Save();

                        repXRefs.Delete(xref.CrossRef_File_EpisodeID);
                    }
                }

                if (animeSeriesID.HasValue)
                {
                    AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
                    AnimeSeries ser = repSeries.GetByID(animeSeriesID.Value);
                    if (ser != null)
                        ser.QueueUpdateStats();
                }

                return "";

            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                return ex.Message;
            }
        }
Example #4
0
        public List<Contract_MissingFile> GetMyListFilesForRemoval(int userID)
        {
            List<Contract_MissingFile> contracts = new List<Contract_MissingFile>();

            /*Contract_MissingFile missingFile2 = new Contract_MissingFile();
            missingFile2.AnimeID = 1;
            missingFile2.AnimeTitle = "Gundam Age";
            missingFile2.EpisodeID = 2;
            missingFile2.EpisodeNumber = 7;
            missingFile2.FileID = 8;
            missingFile2.AnimeSeries = null;
            contracts.Add(missingFile2);

            Thread.Sleep(5000);

            return contracts;*/

            AniDB_FileRepository repAniFile = new AniDB_FileRepository();
            CrossRef_File_EpisodeRepository repFileEp = new CrossRef_File_EpisodeRepository();
            AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();
            AniDB_EpisodeRepository repEpisodes = new AniDB_EpisodeRepository();
            VideoLocalRepository repVids = new VideoLocalRepository();
            AnimeSeriesRepository repSeries = new AnimeSeriesRepository();

            Dictionary<int, AniDB_Anime> animeCache = new Dictionary<int, AniDB_Anime>();
            Dictionary<int, AnimeSeries> animeSeriesCache = new Dictionary<int, AnimeSeries>();

            try
            {
                AniDBHTTPCommand_GetMyList cmd = new AniDBHTTPCommand_GetMyList();
                cmd.Init(ServerSettings.AniDB_Username, ServerSettings.AniDB_Password);
                enHelperActivityType ev = cmd.Process();
                if (ev == enHelperActivityType.GotMyListHTTP)
                {
                    foreach (Raw_AniDB_MyListFile myitem in cmd.MyListItems)
                    {
                        // let's check if the file on AniDB actually exists in the user's local collection
                        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;
                                }
                            }
                        }

                        bool fileMissing = false;
                        if (string.IsNullOrEmpty(hash))
                            fileMissing = true;
                        else
                        {
                            // now check if the file actually exists on disk
                            VideoLocal vid = repVids.GetByHash(hash);

                            if (vid != null && !File.Exists(vid.FullServerPath))
                                fileMissing = true;
                        }

                        if (fileMissing)
                        {

                            // this means we can't find the file
                            AniDB_Anime anime = null;
                            if (animeCache.ContainsKey(myitem.AnimeID))
                                anime = animeCache[myitem.AnimeID];
                            else
                            {
                                anime = repAnime.GetByAnimeID(myitem.AnimeID);
                                animeCache[myitem.AnimeID] = anime;
                            }

                            AnimeSeries ser = null;
                            if (animeSeriesCache.ContainsKey(myitem.AnimeID))
                                ser = animeSeriesCache[myitem.AnimeID];
                            else
                            {
                                ser = repSeries.GetByAnimeID(myitem.AnimeID);
                                animeSeriesCache[myitem.AnimeID] = ser;
                            }

                            Contract_MissingFile missingFile = new Contract_MissingFile();
                            missingFile.AnimeID = myitem.AnimeID;
                            missingFile.AnimeTitle = "Data Missing";
                            if (anime != null) missingFile.AnimeTitle = anime.MainTitle;
                            missingFile.EpisodeID = myitem.EpisodeID;
                            AniDB_Episode ep = repEpisodes.GetByEpisodeID(myitem.EpisodeID);
                            missingFile.EpisodeNumber = -1;
                            missingFile.EpisodeType = 1;
                            if (ep != null)
                            {
                                missingFile.EpisodeNumber = ep.EpisodeNumber;
                                missingFile.EpisodeType = ep.EpisodeType;
                            }
                            missingFile.FileID = myitem.FileID;

                            if (ser == null) missingFile.AnimeSeries = null;
                            else missingFile.AnimeSeries = ser.ToContract(ser.GetUserRecord(userID));

                            contracts.Add(missingFile);
                        }
                    }
                }

                if (contracts.Count > 0)
                {
                    List<SortPropOrFieldAndDirection> sortCriteria = new List<SortPropOrFieldAndDirection>();
                    sortCriteria.Add(new SortPropOrFieldAndDirection("AnimeTitle", false, SortType.eString));
                    sortCriteria.Add(new SortPropOrFieldAndDirection("EpisodeID", false, SortType.eInteger));
                    contracts = Sorting.MultiSort<Contract_MissingFile>(contracts, sortCriteria);
                }
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }
            return contracts;
        }
Example #5
0
        public List<Contract_AnimeEpisode> GetEpisodesForSeriesOld(int animeSeriesID)
        {
            List<Contract_AnimeEpisode> eps = new List<Contract_AnimeEpisode>();
            try
            {

                DateTime start = DateTime.Now;
                AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();
                AnimeSeriesRepository repAnimeSer = new AnimeSeriesRepository();
                CrossRef_File_EpisodeRepository repCrossRefs = new CrossRef_File_EpisodeRepository();

                // get all the data first
                // we do this to reduce the amount of database calls, which makes it a lot faster
                AnimeSeries series = repAnimeSer.GetByID(animeSeriesID);
                if (series == null) return eps;

                List<AnimeEpisode> epList = repEps.GetBySeriesID(animeSeriesID);

                AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository();
                List<AniDB_Episode> aniEpList = repAniEps.GetByAnimeID(series.AniDB_ID);
                Dictionary<int, AniDB_Episode> dictAniEps = new Dictionary<int, AniDB_Episode>();
                foreach (AniDB_Episode aniep in aniEpList)
                    dictAniEps[aniep.EpisodeID] = aniep;

                List<CrossRef_File_Episode> crossRefList = repCrossRefs.GetByAnimeID(series.AniDB_ID);

                TimeSpan ts = DateTime.Now - start;
                logger.Info("GetEpisodesForSeries: {0} (Database) in {1} ms", series.GetAnime().MainTitle, ts.TotalMilliseconds);

                start = DateTime.Now;
                foreach (AnimeEpisode ep in epList)
                {
                    List<CrossRef_File_Episode> xrefs = new List<CrossRef_File_Episode>();
                    foreach (CrossRef_File_Episode xref in crossRefList)
                    {
                        if (ep.AniDB_EpisodeID == xref.EpisodeID)
                            xrefs.Add(xref);
                    }

                    if (dictAniEps.ContainsKey(ep.AniDB_EpisodeID))
                        eps.Add(ep.ToContractOld(dictAniEps[ep.AniDB_EpisodeID]));
                }

                ts = DateTime.Now - start;
                logger.Info("GetEpisodesForSeries: {0} (Contracts) in {1} ms", series.GetAnime().MainTitle, ts.TotalMilliseconds);
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }

            return eps;
        }
Example #6
0
        public List<Contract_AnimeEpisode> GetEpisodesForSeries(int animeSeriesID, int userID)
        {
            List<Contract_AnimeEpisode> eps = new List<Contract_AnimeEpisode>();
            try
            {

                DateTime start = DateTime.Now;
                AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();
                AnimeEpisode_UserRepository repEpUsers = new AnimeEpisode_UserRepository();
                AnimeSeriesRepository repAnimeSer = new AnimeSeriesRepository();
                VideoLocalRepository repVids = new VideoLocalRepository();
                CrossRef_File_EpisodeRepository repCrossRefs = new CrossRef_File_EpisodeRepository();

                // get all the data first
                // we do this to reduce the amount of database calls, which makes it a lot faster
                AnimeSeries series = repAnimeSer.GetByID(animeSeriesID);
                if (series == null) return eps;

                List<AnimeEpisode> epList = repEps.GetBySeriesID(animeSeriesID);
                List<AnimeEpisode_User> userRecordList = repEpUsers.GetByUserIDAndSeriesID(userID, animeSeriesID);
                Dictionary<int, AnimeEpisode_User> dictUserRecords = new Dictionary<int, AnimeEpisode_User>();
                foreach (AnimeEpisode_User epuser in userRecordList)
                    dictUserRecords[epuser.AnimeEpisodeID] = epuser;

                AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository();
                List<AniDB_Episode> aniEpList = repAniEps.GetByAnimeID(series.AniDB_ID);
                Dictionary<int, AniDB_Episode> dictAniEps = new Dictionary<int, AniDB_Episode>();
                foreach (AniDB_Episode aniep in aniEpList)
                    dictAniEps[aniep.EpisodeID] = aniep;

                // get all the video local records and cross refs
                List<VideoLocal> vids = repVids.GetByAniDBAnimeID(series.AniDB_ID);
                List<CrossRef_File_Episode> crossRefs = repCrossRefs.GetByAnimeID(series.AniDB_ID);

                TimeSpan ts = DateTime.Now - start;
                logger.Info("GetEpisodesForSeries: {0} (Database) in {1} ms", series.GetAnime().MainTitle, ts.TotalMilliseconds);

                start = DateTime.Now;
                foreach (AnimeEpisode ep in epList)
                {
                    if (dictAniEps.ContainsKey(ep.AniDB_EpisodeID))
                    {
                        List<VideoLocal> epVids = new List<VideoLocal>();
                        foreach (CrossRef_File_Episode xref in crossRefs)
                        {
                            if (xref.EpisodeID == dictAniEps[ep.AniDB_EpisodeID].EpisodeID)
                            {
                                // don't add the same file twice, this will occur when
                                // one file appears over more than one episodes
                                Dictionary<string, string> addedFiles = new Dictionary<string, string>();
                                foreach (VideoLocal vl in vids)
                                {
                                    if (string.Equals(xref.Hash, vl.Hash, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        if (!addedFiles.ContainsKey(xref.Hash.Trim().ToUpper()))
                                        {
                                            addedFiles[xref.Hash.Trim().ToUpper()] = xref.Hash.Trim().ToUpper();
                                            epVids.Add(vl);
                                        }
                                    }
                                }
                            }
                        }

                        AnimeEpisode_User epuser = null;
                        if (dictUserRecords.ContainsKey(ep.AnimeEpisodeID))
                            epuser = dictUserRecords[ep.AnimeEpisodeID];

                        eps.Add(ep.ToContract(dictAniEps[ep.AniDB_EpisodeID], epVids, epuser, null));
                    }
                }

                ts = DateTime.Now - start;
                logger.Info("GetEpisodesForSeries: {0} (Contracts) in {1} ms", series.GetAnime().MainTitle, ts.TotalMilliseconds);
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }

            return eps;
        }
Example #7
0
        public string AssociateSingleFileWithMultipleEpisodes(int videoLocalID, int animeSeriesID, int startEpNum, int endEpNum)
        {
            try
            {
                VideoLocalRepository repVids = new VideoLocalRepository();
                VideoLocal vid = repVids.GetByID(videoLocalID);
                if (vid == null)
                    return "Could not find video record";

                AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();
                AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
                AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository();
                CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository();

                AnimeSeries ser = repSeries.GetByID(animeSeriesID);
                if (ser == null)
                    return "Could not find anime series record";

                for (int i = startEpNum; i <= endEpNum; i++)
                {
                    List<AniDB_Episode> anieps = repAniEps.GetByAnimeIDAndEpisodeNumber(ser.AniDB_ID, i);
                    if (anieps.Count == 0)
                        return "Could not find the AniDB episode record";

                    AniDB_Episode aniep = anieps[0];

                    List<AnimeEpisode> eps = repEps.GetByAniEpisodeIDAndSeriesID(aniep.EpisodeID, ser.AnimeSeriesID);
                    if (eps.Count == 0)
                        return "Could not find episode record";

                    AnimeEpisode ep = eps[0];

                    CrossRef_File_Episode xref = new CrossRef_File_Episode();
                    xref.PopulateManually(vid, ep);
                    repXRefs.Save(xref);

                    CommandRequest_WebCacheSendXRefFileEpisode cr = new CommandRequest_WebCacheSendXRefFileEpisode(xref.CrossRef_File_EpisodeID);
                    cr.Save();
                }

                vid.RenameIfRequired();
                vid.MoveFileIfRequired();

                ser.QueueUpdateStats();

                // update epidsode added stats
                ser.EpisodeAddedDate = DateTime.Now;
                repSeries.Save(ser);

                AnimeGroupRepository repGroups = new AnimeGroupRepository();
                foreach (AnimeGroup grp in ser.AllGroupsAbove)
                {
                    grp.EpisodeAddedDate = DateTime.Now;
                    repGroups.Save(grp);
                }

                return "";

            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }

            return "";
        }
Example #8
0
        public string AssociateSingleFile(int videoLocalID, int animeEpisodeID)
        {
            try
            {
                VideoLocalRepository repVids = new VideoLocalRepository();
                VideoLocal vid = repVids.GetByID(videoLocalID);
                if (vid == null)
                    return "Could not find video record";

                AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();
                AnimeEpisode ep = repEps.GetByID(animeEpisodeID);
                if (ep == null)
                    return "Could not find episode record";

                CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository();
                CrossRef_File_Episode xref = new CrossRef_File_Episode();
                try
                {
                    xref.PopulateManually(vid, ep);
                }
                catch (Exception ex)
                {
                    string msg = string.Format("Error populating XREF: {0}", vid.ToStringDetailed());
                    throw;
                }
                repXRefs.Save(xref);

                vid.RenameIfRequired();
                vid.MoveFileIfRequired();

                CommandRequest_WebCacheSendXRefFileEpisode cr = new CommandRequest_WebCacheSendXRefFileEpisode(xref.CrossRef_File_EpisodeID);
                cr.Save();

                AnimeSeries ser = ep.GetAnimeSeries();
                ser.QueueUpdateStats();

                // update epidsode added stats
                AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
                ser.EpisodeAddedDate = DateTime.Now;
                repSeries.Save(ser);

                AnimeGroupRepository repGroups = new AnimeGroupRepository();
                foreach (AnimeGroup grp in ser.AllGroupsAbove)
                {
                    grp.EpisodeAddedDate = DateTime.Now;
                    repGroups.Save(grp);
                }

                CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vid.Hash);
                cmdAddFile.Save();

                return "";

            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }

            return "";
        }
Example #9
0
        private VideoLocal ProcessFile_LocalInfo()
        {
            // hash and read media info for file
            int nshareID = -1;
            string filePath = "";

            ImportFolderRepository repNS = new ImportFolderRepository();
            List<ImportFolder> shares = repNS.GetAll();
            DataAccessHelper.GetShareAndPath(FileName, shares, ref nshareID, ref filePath);

            if (!File.Exists(FileName))
            {
                logger.Error("File does not exist: {0}", FileName);
                return null;
            }

            int numAttempts = 0;
            // Wait 3 minutes seconds before giving up on trying to access the file
            while ((!CanAccessFile(FileName)) && (numAttempts < 180))
            {
                numAttempts++;
                Thread.Sleep(1000);
                Console.WriteLine("Attempt # " + numAttempts.ToString());
            }

            // if we failed to access the file, get ouuta here
            if (numAttempts == 180)
            {
                logger.Error("Could not access file: " + FileName);
                return null;
            }

            // check if we have already processed this file
            VideoLocal vlocal = null;
            VideoLocalRepository repVidLocal = new VideoLocalRepository();
            FileNameHashRepository repFNHash = new FileNameHashRepository();

            List<VideoLocal> vidLocals = repVidLocal.GetByFilePathAndShareID(filePath, nshareID);
            FileInfo fi = new FileInfo(FileName);

            if (vidLocals.Count > 0)
            {
                vlocal = vidLocals[0];
                logger.Trace("VideoLocal record found in database: {0}", vlocal.VideoLocalID);

                if (ForceHash)
                {
                    vlocal.FileSize = fi.Length;
                    vlocal.DateTimeUpdated = DateTime.Now;
                }
            }
            else
            {
                logger.Trace("VideoLocal, creating new record");
                vlocal = new VideoLocal();
                vlocal.DateTimeUpdated = DateTime.Now;
                vlocal.DateTimeCreated = vlocal.DateTimeUpdated;
                vlocal.FilePath = filePath;
                vlocal.FileSize = fi.Length;
                vlocal.ImportFolderID = nshareID;
                vlocal.Hash = "";
                vlocal.CRC32 = "";
                vlocal.MD5 = "";
                vlocal.SHA1 = "";
                vlocal.IsIgnored = 0;
                vlocal.IsVariation = 0;
            }

            // check if we need to get a hash this file
            Hashes hashes = null;
            if (string.IsNullOrEmpty(vlocal.Hash) || ForceHash)
            {
                // try getting the hash from the CrossRef
                if (!ForceHash)
                {
                    CrossRef_File_EpisodeRepository repCrossRefs = new CrossRef_File_EpisodeRepository();
                    List<CrossRef_File_Episode> crossRefs = repCrossRefs.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize);
                    if (crossRefs.Count == 1)
                    {
                        vlocal.Hash = crossRefs[0].Hash;
                        vlocal.HashSource = (int)HashSource.DirectHash;
                    }
                }

                // try getting the hash from the LOCAL cache
                if (!ForceHash && string.IsNullOrEmpty(vlocal.Hash))
                {
                    List<FileNameHash> fnhashes = repFNHash.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize);
                    if (fnhashes != null && fnhashes.Count > 1)
                    {
                        // if we have more than one record it probably means there is some sort of corruption
                        // lets delete the local records
                        foreach (FileNameHash fnh in fnhashes)
                        {
                            repFNHash.Delete(fnh.FileNameHashID);
                        }
                    }

                    if (fnhashes != null && fnhashes.Count == 1)
                    {
                        logger.Trace("Got hash from LOCAL cache: {0} ({1})", FileName, fnhashes[0].Hash);
                        vlocal.Hash = fnhashes[0].Hash;
                        vlocal.HashSource = (int)HashSource.WebCacheFileName;
                    }
                }

                // hash the file
                if (string.IsNullOrEmpty(vlocal.Hash) || ForceHash)
                {
                    DateTime start = DateTime.Now;
                    logger.Trace("Calculating hashes for: {0}", FileName);
                    // update the VideoLocal record with the Hash
                    hashes = FileHashHelper.GetHashInfo(FileName, true, MainWindow.OnHashProgress, ServerSettings.Hash_CRC32, ServerSettings.Hash_MD5, ServerSettings.Hash_SHA1);
                    TimeSpan ts = DateTime.Now - start;
                    logger.Trace("Hashed file in {0} seconds --- {1} ({2})", ts.TotalSeconds.ToString("#0.0"), FileName, Utils.FormatByteSize(vlocal.FileSize));

                    vlocal.Hash = hashes.ed2k;
                    vlocal.CRC32 = hashes.crc32;
                    vlocal.MD5 = hashes.md5;
                    vlocal.SHA1 = hashes.sha1;
                    vlocal.HashSource = (int)HashSource.DirectHash;
                }

                // We should have a hash by now
                // before we save it, lets make sure there is not any other record with this hash (possible duplicate file)
                VideoLocal vidTemp = repVidLocal.GetByHash(vlocal.Hash);
                if (vidTemp != null)
                {
                    // don't delete it, if it is actually the same record
                    if (vidTemp.VideoLocalID != vlocal.VideoLocalID)
                    {
                        // delete the VideoLocal record
                        logger.Warn("Deleting duplicate video file record");
                        logger.Warn("---------------------------------------------");
                        logger.Warn("Keeping record for: {0}", vlocal.FullServerPath);
                        logger.Warn("Deleting record for: {0}", vidTemp.FullServerPath);
                        logger.Warn("---------------------------------------------");

                        // check if we have a record of this in the database, if not create one
                        DuplicateFileRepository repDups = new DuplicateFileRepository();
                        List<DuplicateFile> dupFiles = repDups.GetByFilePathsAndImportFolder(vlocal.FilePath, vidTemp.FilePath, vlocal.ImportFolderID, vidTemp.ImportFolderID);
                        if (dupFiles.Count == 0)
                            dupFiles = repDups.GetByFilePathsAndImportFolder(vidTemp.FilePath, vlocal.FilePath, vidTemp.ImportFolderID, vlocal.ImportFolderID);

                        if (dupFiles.Count == 0)
                        {
                            DuplicateFile dup = new DuplicateFile();
                            dup.DateTimeUpdated = DateTime.Now;
                            dup.FilePathFile1 = vlocal.FilePath;
                            dup.FilePathFile2 = vidTemp.FilePath;
                            dup.ImportFolderIDFile1 = vlocal.ImportFolderID;
                            dup.ImportFolderIDFile2 = vidTemp.ImportFolderID;
                            dup.Hash = vlocal.Hash;
                            repDups.Save(dup);
                        }

                        repVidLocal.Delete(vidTemp.VideoLocalID);
                    }
                }

                repVidLocal.Save(vlocal);

                // also save the filename to hash record
                // replace the existing records just in case it was corrupt
                FileNameHash fnhash = null;
                List<FileNameHash> fnhashes2 = repFNHash.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize);
                if (fnhashes2 != null && fnhashes2.Count > 1)
                {
                    // if we have more than one record it probably means there is some sort of corruption
                    // lets delete the local records
                    foreach (FileNameHash fnh in fnhashes2)
                    {
                        repFNHash.Delete(fnh.FileNameHashID);
                    }
                }

                if (fnhashes2 != null && fnhashes2.Count == 1)
                    fnhash = fnhashes2[0];
                else
                    fnhash = new FileNameHash();

                fnhash.FileName = Path.GetFileName(vlocal.FilePath);
                fnhash.FileSize = vlocal.FileSize;
                fnhash.Hash = vlocal.Hash;
                fnhash.DateTimeUpdated = DateTime.Now;
                repFNHash.Save(fnhash);
            }

            // now check if we have stored a VideoInfo record
            bool refreshMediaInfo = false;

            VideoInfoRepository repVidInfo = new VideoInfoRepository();
            VideoInfo vinfo = repVidInfo.GetByHash(vlocal.Hash);

            if (vinfo == null)
            {
                refreshMediaInfo = true;

                vinfo = new VideoInfo();
                vinfo.Hash = vlocal.Hash;

                vinfo.Duration = 0;
                vinfo.FileSize = fi.Length;
                vinfo.DateTimeUpdated = DateTime.Now;
                vinfo.FileName = filePath;

                vinfo.AudioBitrate = "";
                vinfo.AudioCodec = "";
                vinfo.VideoBitrate = "";
                vinfo.VideoBitDepth = "";
                vinfo.VideoCodec = "";
                vinfo.VideoFrameRate = "";
                vinfo.VideoResolution = "";

                repVidInfo.Save(vinfo);
            }
            else
            {
                // check if we need to update the media info
                if (vinfo.VideoCodec.Trim().Length == 0) refreshMediaInfo = true;
                else refreshMediaInfo = false;

            }

            if (refreshMediaInfo)
            {
                logger.Trace("Getting media info for: {0}", FileName);
                MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(FileName, true);

                vinfo.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate;
                vinfo.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec;

                vinfo.DateTimeUpdated = vlocal.DateTimeUpdated;
                vinfo.Duration = mInfo.Duration;
                vinfo.FileName = filePath;
                vinfo.FileSize = fi.Length;

                vinfo.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate;
                vinfo.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth;
                vinfo.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec;
                vinfo.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate;
                vinfo.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution;
                vinfo.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo;
                repVidInfo.Save(vinfo);
            }

            // now add a command to process the file
            CommandRequest_ProcessFile cr_procfile = new CommandRequest_ProcessFile(vlocal.VideoLocalID, false);
            cr_procfile.Save();

            return vlocal;
        }
Example #10
0
		public void ToggleWatchedStatus(bool watched, bool updateOnline, DateTime? watchedDate, bool updateStats, bool updateStatsCache, int userID, 
			bool scrobbleTrakt, bool updateWatchedDate)
		{
			VideoLocalRepository repVids = new VideoLocalRepository();
			AnimeEpisodeRepository repEpisodes = new AnimeEpisodeRepository();
			AniDB_FileRepository repAniFile = new AniDB_FileRepository();
			CrossRef_File_EpisodeRepository repCross = new CrossRef_File_EpisodeRepository();
			VideoLocal_UserRepository repVidUsers = new VideoLocal_UserRepository();
			JMMUserRepository repUsers = new JMMUserRepository();
			AnimeEpisode_UserRepository repEpisodeUsers = new AnimeEpisode_UserRepository();

			JMMUser user = repUsers.GetByID(userID);
			if (user == null) return;

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

			// update the video file to watched
			int mywatched = watched ? 1 : 0;

			if (user.IsAniDBUser == 0)
				SaveWatchedStatus(watched, userID, watchedDate, updateWatchedDate);
			else
			{
				// if the user is AniDB user we also want to update any other AniDB
				// users to keep them in sync
				foreach (JMMUser juser in aniDBUsers)
				{
					if (juser.IsAniDBUser == 1)
						SaveWatchedStatus(watched, juser.JMMUserID, watchedDate, updateWatchedDate);
				}
			}
			

			// now lets find all the associated AniDB_File record if there is one
			if (user.IsAniDBUser == 1)
			{
				AniDB_File aniFile = repAniFile.GetByHash(this.Hash);
				if (aniFile != null)
				{
					aniFile.IsWatched = mywatched;

					if (watched)
					{
						if (watchedDate.HasValue)
							aniFile.WatchedDate = watchedDate;
						else
							aniFile.WatchedDate = DateTime.Now;
					}
					else
						aniFile.WatchedDate = null;


					repAniFile.Save(aniFile, false);

					
				}

				if (updateOnline)
				{
					if ((watched && ServerSettings.AniDB_MyList_SetWatched) || (!watched && ServerSettings.AniDB_MyList_SetUnwatched))
					{
						CommandRequest_UpdateMyListFileStatus cmd = new CommandRequest_UpdateMyListFileStatus(this.Hash, watched, false, 
							watchedDate.HasValue ? Utils.GetAniDBDateAsSeconds(watchedDate) : 0);
						cmd.Save();
					}
				}
			}

			// now find all the episode records associated with this video file
			// but we also need to check if theer are any other files attached to this episode with a watched
			// status, 


			AnimeSeries ser = null;
			// get all files associated with this episode
			List<CrossRef_File_Episode> xrefs = repCross.GetByHash(this.Hash);
			if (watched)
			{
				// find the total watched percentage
				// eg one file can have a % = 100
				// or if 2 files make up one episodes they will each have a % = 50

				foreach (CrossRef_File_Episode xref in xrefs)
				{
					// get the episode for this file
					AnimeEpisode ep = repEpisodes.GetByAniDBEpisodeID(xref.EpisodeID);
					if (ep == null) continue;

					// get all the files for this episode
					int epPercentWatched = 0;
					foreach (CrossRef_File_Episode filexref in ep.FileCrossRefs)
					{
						VideoLocal_User vidUser = filexref.GetVideoLocalUserRecord(userID);
						if (vidUser != null)
						{
							// if not null means it is watched
							epPercentWatched += filexref.Percentage;
						}

						if (epPercentWatched > 95) break;
					}

					if (epPercentWatched > 95)
					{
						ser = ep.GetAnimeSeries();

						if (user.IsAniDBUser == 0)
							ep.SaveWatchedStatus(true, userID, watchedDate, updateWatchedDate);
						else
						{
							// if the user is AniDB user we also want to update any other AniDB
							// users to keep them in sync
							foreach (JMMUser juser in aniDBUsers)
							{
								if (juser.IsAniDBUser == 1)
									ep.SaveWatchedStatus(true, juser.JMMUserID, watchedDate, updateWatchedDate);
							}
						}

						if (scrobbleTrakt && !string.IsNullOrEmpty(ServerSettings.Trakt_Username) && !string.IsNullOrEmpty(ServerSettings.Trakt_Password))
						{
							CommandRequest_TraktShowScrobble cmdScrobble = new CommandRequest_TraktShowScrobble(ep.AnimeEpisodeID);
							cmdScrobble.Save();
						}

						if (!string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password))
						{
							CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID);
							cmdMAL.Save();
						}
					}
				}

				
			}
			else
			{
				// if setting a file to unwatched only set the episode unwatched, if ALL the files are unwatched
				foreach (CrossRef_File_Episode xrefEp in xrefs)
				{
					AnimeEpisode ep = repEpisodes.GetByAniDBEpisodeID(xrefEp.EpisodeID);
					if (ep == null) continue;
					ser = ep.GetAnimeSeries();

					// get all the files for this episode
					int epPercentWatched = 0;
					foreach (CrossRef_File_Episode filexref in ep.FileCrossRefs)
					{
						VideoLocal_User vidUser = filexref.GetVideoLocalUserRecord(userID);
						if (vidUser != null)
							epPercentWatched += filexref.Percentage;

						if (epPercentWatched > 95) break;
					}

					if (epPercentWatched < 95)
					{
						if (user.IsAniDBUser == 0)
							ep.SaveWatchedStatus(false, userID, watchedDate, true);
						else
						{
							// if the user is AniDB user we also want to update any other AniDB
							// users to keep them in sync
							foreach (JMMUser juser in aniDBUsers)
							{
								if (juser.IsAniDBUser == 1)
									ep.SaveWatchedStatus(false, juser.JMMUserID, watchedDate, true);
							}
						}

						CommandRequest_TraktShowEpisodeUnseen cmdUnseen = new CommandRequest_TraktShowEpisodeUnseen(ep.AnimeEpisodeID);
						cmdUnseen.Save();
					}
				}

				if (!string.IsNullOrEmpty(ServerSettings.MAL_Username) && !string.IsNullOrEmpty(ServerSettings.MAL_Password))
				{
					CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID);
					cmdMAL.Save();
				}
			}
			

			// update stats for groups and series
			if (ser != null && updateStats)
			{
				// update all the groups above this series in the heirarchy
				ser.UpdateStats(true, true, true);
				//ser.TopLevelAnimeGroup.UpdateStatsFromTopLevel(true, true, true);
			}

			if (ser != null && updateStatsCache)
				StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID);
		}
Example #11
0
		public void UpdateUsingGroup(ISession session, int animeGroupID)
		{
			try
			{
				DateTime start = DateTime.Now;

				AnimeGroupRepository repGroups = new AnimeGroupRepository();
				AnimeGroup thisgrp = repGroups.GetByID(session, animeGroupID);
				
				if (thisgrp == null) return;

				AdhocRepository repAdHoc = new AdhocRepository();

				// get a list of all the groups including this one and everthing above it the heirarchy
				List<AnimeGroup> allgroups = new List<AnimeGroup>();
				allgroups.Add(thisgrp);

				int? groupID = thisgrp.AnimeGroupParentID;
				while (groupID.HasValue)
				{
					AnimeGroup grpTemp = repGroups.GetByID(session, groupID.Value);
					if (grpTemp != null)
					{
						allgroups.Add(grpTemp);
						groupID = grpTemp.AnimeGroupParentID;
					}
					else
						groupID = null;
				}

				TimeSpan ts = DateTime.Now - start;
				logger.Trace("Updating cached stats for GROUP - STEP 1 ({0}) in {1} ms", thisgrp.GroupName, ts.TotalMilliseconds);
				start = DateTime.Now;

				VideoLocalRepository repVids = new VideoLocalRepository();
				CrossRef_File_EpisodeRepository repXrefs = new CrossRef_File_EpisodeRepository();

				foreach (AnimeGroup grp in allgroups)
				{
					StatGroupCategories[grp.AnimeGroupID] = grp.CategoriesString;
					StatGroupTitles[grp.AnimeGroupID] = grp.TitlesString;
					StatGroupVideoQuality[grp.AnimeGroupID] = grp.VideoQualityString;

					ts = DateTime.Now - start;
					logger.Trace("Updating cached stats for GROUP - STEP 2 ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
					start = DateTime.Now;

					DateTime? airDate_Min = null;
					DateTime? airDate_Max = null;
					DateTime? endDate = new DateTime(1980, 1, 1);
					DateTime? seriesCreatedDate = null;
					bool isComplete = false;
					bool hasFinishedAiring = false;
					bool isCurrentlyAiring = false;
					string videoQualityEpisodes = "";

					List<string> audioLanguages = new List<string>();
					List<string> subtitleLanguages = new List<string>();

					bool hasTvDB = true;
					bool hasMAL = true;
					bool hasMovieDB = true;
					bool hasMovieDBOrTvDB = true;

					int seriesCount = 0;
					int epCount = 0;


					foreach (AnimeSeries series in grp.GetAllSeries(session))
					{
						seriesCount++;

						List<VideoLocal> vidsTemp = repVids.GetByAniDBAnimeID(session, series.AniDB_ID);
						List<CrossRef_File_Episode> crossRefs = repXrefs.GetByAnimeID(session, series.AniDB_ID);

						Dictionary<int, List<CrossRef_File_Episode>> dictCrossRefs = new Dictionary<int, List<CrossRef_File_Episode>>();
						foreach (CrossRef_File_Episode xref in crossRefs)
						{
							if (!dictCrossRefs.ContainsKey(xref.EpisodeID))
								dictCrossRefs[xref.EpisodeID] = new List<CrossRef_File_Episode>();
							dictCrossRefs[xref.EpisodeID].Add(xref);
						}

						Dictionary<string, VideoLocal> dictVids = new Dictionary<string, VideoLocal>();
						foreach (VideoLocal vid in vidsTemp)
							dictVids[vid.Hash] = vid;

						// All Video Quality Episodes
						// Try to determine if this anime has all the episodes available at a certain video quality
						// e.g.  the series has all episodes in blu-ray
						// Also look at languages
						Dictionary<string, int> vidQualEpCounts = new Dictionary<string,int>(); // video quality, count of episodes

						foreach (AnimeEpisode ep in series.GetAnimeEpisodes(session))
						{
							if (ep.EpisodeTypeEnum != AniDBAPI.enEpisodeType.Episode) continue;


							List<VideoLocal> epVids = new List<VideoLocal>();
							if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID))
							{
								foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID])
								{
									if (xref.EpisodeID == ep.AniDB_EpisodeID)
									{
										if (dictVids.ContainsKey(xref.Hash))
											epVids.Add(dictVids[xref.Hash]);
									}
								}
							}

							List<string> qualityAddedSoFar = new List<string>(); // handle mutliple files of the same quality for one episode
							foreach (VideoLocal vid in epVids)
							{
								AniDB_File anifile = vid.GetAniDBFile(session);
								if (anifile == null) continue;

								if (!qualityAddedSoFar.Contains(anifile.File_Source))
								{
									if (!vidQualEpCounts.ContainsKey(anifile.File_Source))
										vidQualEpCounts[anifile.File_Source] = 1;
									else
										vidQualEpCounts[anifile.File_Source]++;

									qualityAddedSoFar.Add(anifile.File_Source);
								}
							}
						}

						ts = DateTime.Now - start;
						logger.Trace("Updating cached stats for GROUP/Series - STEP 3 ({0}/{1}) in {2} ms",grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
						start = DateTime.Now;



						AniDB_Anime anime = series.GetAnime(session);

						epCount = epCount + anime.EpisodeCountNormal;

						foreach (KeyValuePair<string, int> kvp in vidQualEpCounts)
						{
							int index = videoQualityEpisodes.IndexOf(kvp.Key, 0, StringComparison.InvariantCultureIgnoreCase);
							if (index > -1) continue; // don't add if we already have it

							if (anime.EpisodeCountNormal == kvp.Value)
							{
								if (videoQualityEpisodes.Length > 0) videoQualityEpisodes += ",";
								videoQualityEpisodes += kvp.Key;
							}

						}

						ts = DateTime.Now - start;
						logger.Trace("Updating cached stats for GROUP/Series - STEP 4 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
						start = DateTime.Now;

						// audio languages
						Dictionary<int, LanguageStat> dicAudio = repAdHoc.GetAudioLanguageStatsByAnime(session, anime.AnimeID);
						foreach (KeyValuePair<int, LanguageStat> kvp in dicAudio)
						{
							foreach (string lanName in kvp.Value.LanguageNames)
							{
								if (!audioLanguages.Contains(lanName))
									audioLanguages.Add(lanName);
							}
						}

						ts = DateTime.Now - start;
						logger.Trace("Updating cached stats for GROUP/Series - STEP 5 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
						start = DateTime.Now;

						// subtitle languages
						Dictionary<int, LanguageStat> dicSubtitle = repAdHoc.GetSubtitleLanguageStatsByAnime(session, anime.AnimeID);
						foreach (KeyValuePair<int, LanguageStat> kvp in dicSubtitle)
						{
							foreach (string lanName in kvp.Value.LanguageNames)
							{
								if (!subtitleLanguages.Contains(lanName))
									subtitleLanguages.Add(lanName);
							}
						}

						ts = DateTime.Now - start;
						logger.Trace("Updating cached stats for GROUP/Series - STEP 6 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
						start = DateTime.Now;

						// Calculate Air Date 
						DateTime? thisDate = series.AirDate;
						if (thisDate.HasValue)
						{
							if (airDate_Min.HasValue)
							{
								if (thisDate.Value < airDate_Min.Value) airDate_Min = thisDate;
							}
							else
								airDate_Min = thisDate;

							if (airDate_Max.HasValue)
							{
								if (thisDate.Value > airDate_Max.Value) airDate_Max = thisDate;
							}
							else
								airDate_Max = thisDate;
						}

						// calculate end date
						// if the end date is NULL it actually means it is ongoing, so this is the max possible value
						thisDate = series.EndDate;
						if (thisDate.HasValue && endDate.HasValue)
						{
							if (thisDate.Value > endDate.Value) endDate = thisDate;
						}
						else
							endDate = null;

						// Note - only one series has to be finished airing to qualify
						if (series.EndDate.HasValue && series.EndDate.Value < DateTime.Now)
							hasFinishedAiring = true;

						// Note - only one series has to be finished airing to qualify
						if (!series.EndDate.HasValue || series.EndDate.Value > DateTime.Now)
							isCurrentlyAiring = true;

						// We evaluate IsComplete as true if
						// 1. series has finished airing
						// 2. user has all episodes locally
						// Note - only one series has to be complete for the group to be considered complete
						if (series.EndDate.HasValue)
						{
							if (series.EndDate.Value < DateTime.Now && series.MissingEpisodeCount == 0 && series.MissingEpisodeCountGroups == 0)
							{
								isComplete = true;
							}
						}

						// Calculate Series Created Date 
						thisDate = series.DateTimeCreated;
						if (thisDate.HasValue)
						{
							if (seriesCreatedDate.HasValue)
							{
								if (thisDate.Value < seriesCreatedDate.Value) seriesCreatedDate = thisDate;
							}
							else
								seriesCreatedDate = thisDate;
						}

						ts = DateTime.Now - start;
						logger.Trace("Updating cached stats for GROUP/Series - STEP 7 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
						start = DateTime.Now;

						// for the group, if any of the series don't have a tvdb link
						// we will consider the group as not having a tvdb link

						List<CrossRef_AniDB_TvDBV2> tvXrefs = series.GetCrossRefTvDBV2();

						if (tvXrefs == null || tvXrefs.Count == 0) hasTvDB = false;
						if (series.CrossRefMovieDB == null) hasMovieDB = false;
						if (series.CrossRefMAL == null) hasMAL = false;

						if ((tvXrefs == null || tvXrefs.Count == 0) && series.CrossRefMovieDB == null) hasMovieDBOrTvDB = false;
					}


					StatGroupIsComplete[grp.AnimeGroupID] = isComplete;
					StatGroupIsFinishedAiring[grp.AnimeGroupID] = hasFinishedAiring;
					StatGroupIsCurrentlyAiring[grp.AnimeGroupID] = isCurrentlyAiring;
					StatGroupHasTvDB[grp.AnimeGroupID] = hasTvDB;
					StatGroupHasMAL[grp.AnimeGroupID] = hasMAL;
					StatGroupHasMovieDB[grp.AnimeGroupID] = hasMovieDB;
					StatGroupHasMovieDBOrTvDB[grp.AnimeGroupID] = hasMovieDBOrTvDB;
					StatGroupSeriesCount[grp.AnimeGroupID] = seriesCount;
					StatGroupEpisodeCount[grp.AnimeGroupID] = epCount;

					StatGroupVideoQualityEpisodes[grp.AnimeGroupID] = videoQualityEpisodes;

					StatGroupAirDate_Min[grp.AnimeGroupID] = airDate_Min;
					StatGroupAirDate_Max[grp.AnimeGroupID] = airDate_Max;
					StatGroupEndDate[grp.AnimeGroupID] = endDate;
					StatGroupSeriesCreatedDate[grp.AnimeGroupID] = seriesCreatedDate;

					StatGroupUserVoteOverall[grp.AnimeGroupID] = grp.UserVote;
					StatGroupUserVotePermanent[grp.AnimeGroupID] = grp.UserVotePermanent;
					StatGroupUserVoteTemporary[grp.AnimeGroupID] = grp.UserVoteTemporary;
					StatGroupAniDBRating[grp.AnimeGroupID] = grp.AniDBRating;

					ts = DateTime.Now - start;
					logger.Trace("Updating cached stats for GROUP - STEP 8 ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
					start = DateTime.Now;

					string Stat_AudioLanguages = "";
					foreach (string audioLan in audioLanguages)
					{
						if (Stat_AudioLanguages.Length > 0) Stat_AudioLanguages += ",";
						Stat_AudioLanguages += audioLan;
					}
					this.StatGroupAudioLanguages[grp.AnimeGroupID] = Stat_AudioLanguages;

					string Stat_SubtitleLanguages = "";
					foreach (string subLan in subtitleLanguages)
					{
						if (Stat_SubtitleLanguages.Length > 0) Stat_SubtitleLanguages += ",";
						Stat_SubtitleLanguages += subLan;
					}
					this.StatGroupSubtitleLanguages[grp.AnimeGroupID] = Stat_SubtitleLanguages;

                    ts = DateTime.Now - start;
                    logger.Trace("Updating cached stats for GROUP - STEP 9 ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
                    start = DateTime.Now;
                    UpdateGroupFilterUsingGroup(grp.AnimeGroupID);
                    UpdatePlexAnimeGroup(session, grp,grp.GetAllSeries());
                    ts = DateTime.Now - start;
                    logger.Trace("Updating cached stats for GROUP - END ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
                }
			}
			catch (Exception ex)
			{
				logger.ErrorException(ex.ToString(), ex);
			}
		}
Example #12
0
		public void CreateCrossEpisodes(string localFileName)
		{
			if (episodesRAW != null) //Only create relations if the origin of the data if from Raw (AniDB)
			{
				CrossRef_File_EpisodeRepository repFileEpisodes = new CrossRef_File_EpisodeRepository();
				List<CrossRef_File_Episode> fileEps = repFileEpisodes.GetByHash(this.Hash);

				foreach (CrossRef_File_Episode fileEp in fileEps)
					repFileEpisodes.Delete(fileEp.CrossRef_File_EpisodeID);

				char apostrophe = ("'").ToCharArray()[0];
				char epiSplit = ',';
				if (episodesRAW.Contains(apostrophe))
					epiSplit = apostrophe;

				char eppSplit = ',';
				if (episodesPercentRAW.Contains(apostrophe))
					eppSplit = apostrophe;

				string[] epi = episodesRAW.Split(epiSplit);
				string[] epp = episodesPercentRAW.Split(eppSplit);
				for (int x = 0; x < epi.Length; x++)
				{

					string epis = epi[x].Trim();
					string epps = epp[x].Trim();
					if (epis.Length > 0)
					{
						int epid = 0;
						int.TryParse(epis, out epid);
						int eppp = 100;
						int.TryParse(epps, out eppp);
						if (epid != 0)
						{
							CrossRef_File_Episode cross = new CrossRef_File_Episode();
							cross.Hash = Hash;
							cross.CrossRefSource = (int)CrossRefSource.AniDB;
							cross.AnimeID = this.AnimeID;
							cross.EpisodeID = epid;
							cross.Percentage = eppp;
							cross.EpisodeOrder = x + 1;
							cross.FileName = localFileName;
							cross.FileSize = FileSize;
							repFileEpisodes.Save(cross);
						}
					}
				}
			}
		}
Example #13
0
		public static void RemoveRecordsWithoutPhysicalFiles()
		{
			VideoLocalRepository repVidLocals = new VideoLocalRepository();
			CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository();

			// get a full list of files
			List<VideoLocal> filesAll = repVidLocals.GetAll();
			foreach (VideoLocal vl in filesAll)
			{
				if (!File.Exists(vl.FullServerPath))
				{
					// delete video local record
					logger.Info("RemoveRecordsWithoutPhysicalFiles : {0}", vl.FullServerPath);
					repVidLocals.Delete(vl.VideoLocalID);

					CommandRequest_DeleteFileFromMyList cmdDel = new CommandRequest_DeleteFileFromMyList(vl.Hash, vl.FileSize);
					cmdDel.Save();
				}
			}

			UpdateAllStats();
		}
		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;
			}
		}
Example #15
0
		void workerMyAnime2_DoWork(object sender, DoWorkEventArgs e)
		{
			MA2Progress ma2Progress = new MA2Progress();
			ma2Progress.CurrentFile = 0;
			ma2Progress.ErrorMessage = "";
			ma2Progress.MigratedFiles = 0;
			ma2Progress.TotalFiles = 0;

			try
			{
				string databasePath = e.Argument as string;

				string connString = string.Format(@"data source={0};useutf16encoding=True", databasePath);
				SQLiteConnection myConn = new SQLiteConnection(connString);
				myConn.Open();

				// get a list of unlinked files
				VideoLocalRepository repVids = new VideoLocalRepository();
				AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository();
				AniDB_AnimeRepository repAniAnime = new AniDB_AnimeRepository();
				AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
				AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();

				List<VideoLocal> vids = repVids.GetVideosWithoutEpisode();
				ma2Progress.TotalFiles = vids.Count;

				foreach (VideoLocal vid in vids)
				{
					ma2Progress.CurrentFile = ma2Progress.CurrentFile + 1;
					workerMyAnime2.ReportProgress(0, ma2Progress);

					// search for this file in the XrossRef table in MA2
					string sql = string.Format("SELECT AniDB_EpisodeID from CrossRef_Episode_FileHash WHERE Hash = '{0}' AND FileSize = {1}", vid.ED2KHash, vid.FileSize);
					SQLiteCommand sqCommand = new SQLiteCommand(sql);
					sqCommand.Connection = myConn;

					SQLiteDataReader myReader = sqCommand.ExecuteReader();
					while (myReader.Read())
					{
						int episodeID = 0;
						if (!int.TryParse(myReader.GetValue(0).ToString(), out episodeID)) continue;
						if (episodeID <= 0) continue;

						sql = string.Format("SELECT AnimeID from AniDB_Episode WHERE EpisodeID = {0}", episodeID);
						sqCommand = new SQLiteCommand(sql);
						sqCommand.Connection = myConn;

						SQLiteDataReader myReader2 = sqCommand.ExecuteReader();
						while (myReader2.Read())
						{
							int animeID = myReader2.GetInt32(0);

							// so now we have all the needed details we can link the file to the episode
							// as long as wehave the details in JMM
							AniDB_Anime anime = null;
							AniDB_Episode ep = repAniEps.GetByEpisodeID(episodeID);
							if (ep == null)
							{
								logger.Debug("Getting Anime record from AniDB....");
								anime = JMMService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.AutoGroupSeries);
							}
							else
								anime = repAniAnime.GetByAnimeID(animeID);

							// create the group/series/episode records if needed
							AnimeSeries ser = null;
							if (anime == null) continue;

							logger.Debug("Creating groups, series and episodes....");
							// check if there is an AnimeSeries Record associated with this AnimeID
							ser = repSeries.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
							AniDB_GroupStatusRepository repStatus = new AniDB_GroupStatusRepository();
							if (repStatus.GetByAnimeID(anime.AnimeID).Count == 0)
							{
								CommandRequest_GetReleaseGroupStatus cmdStatus = new CommandRequest_GetReleaseGroupStatus(anime.AnimeID, false);
								cmdStatus.Save();
							}

							// update stats
							ser.EpisodeAddedDate = DateTime.Now;
							repSeries.Save(ser);

							AnimeGroupRepository repGroups = new AnimeGroupRepository();
							foreach (AnimeGroup grp in ser.AllGroupsAbove)
							{
								grp.EpisodeAddedDate = DateTime.Now;
								repGroups.Save(grp);
							}


							AnimeEpisode epAnime = repEps.GetByAniDBEpisodeID(episodeID);
							if (epAnime == null)
								continue;

							CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository();
							CrossRef_File_Episode xref = new CrossRef_File_Episode();

							try
							{
								xref.PopulateManually(vid, epAnime);
							}
							catch (Exception ex)
							{
								string msg = string.Format("Error populating XREF: {0} - {1}", vid.ToStringDetailed(), ex.ToString());
								throw;
							}

							repXRefs.Save(xref);

							vid.RenameIfRequired();
							vid.MoveFileIfRequired();

							// update stats for groups and series
							if (ser != null)
							{
								// update all the groups above this series in the heirarchy
								ser.UpdateStats(true, true, true);
								StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID);
							}


							// Add this file to the users list
							if (ServerSettings.AniDB_MyList_AddFiles)
							{
								CommandRequest_AddFileToMyList cmd = new CommandRequest_AddFileToMyList(vid.ED2KHash);
								cmd.Save();
							}

							ma2Progress.MigratedFiles = ma2Progress.MigratedFiles + 1;
							workerMyAnime2.ReportProgress(0, ma2Progress);

						}
						myReader2.Close();


						//Console.WriteLine(myReader.GetString(0));
					}
					myReader.Close();
				}


				myConn.Close();

				ma2Progress.CurrentFile = ma2Progress.CurrentFile + 1;
				workerMyAnime2.ReportProgress(0, ma2Progress);

			}
			catch (Exception ex)
			{
				logger.ErrorException(ex.ToString(), ex);
				ma2Progress.ErrorMessage = ex.Message;
				workerMyAnime2.ReportProgress(0, ma2Progress);
			}
		}
Example #16
0
        public string AssociateMultipleFiles(List<int> videoLocalIDs, int animeSeriesID, int startingEpisodeNumber, bool singleEpisode)
        {
            try
            {
                CrossRef_File_EpisodeRepository repXRefs = new CrossRef_File_EpisodeRepository();
                AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
                VideoLocalRepository repVids = new VideoLocalRepository();
                AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository();
                AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();

                AnimeSeries ser = repSeries.GetByID(animeSeriesID);
                if (ser == null)
                    return "Could not find anime series record";

                int epNumber = startingEpisodeNumber;
                int count = 1;

                foreach (int videoLocalID in videoLocalIDs)
                {
                    VideoLocal vid = repVids.GetByID(videoLocalID);
                    if (vid == null)
                        return "Could not find video local record";

                    List<AniDB_Episode> anieps = repAniEps.GetByAnimeIDAndEpisodeNumber(ser.AniDB_ID, epNumber);
                    if (anieps.Count == 0)
                        return "Could not find the AniDB episode record";

                    AniDB_Episode aniep = anieps[0];

                    List<AnimeEpisode> eps = repEps.GetByAniEpisodeIDAndSeriesID(aniep.EpisodeID, ser.AnimeSeriesID);
                    if (eps.Count == 0)
                        return "Could not find episode record";

                    AnimeEpisode ep = eps[0];

                    CrossRef_File_Episode xref = new CrossRef_File_Episode();
                    xref.PopulateManually(vid, ep);

                    // TODO do this properly
                    if (singleEpisode)
                    {
                        xref.EpisodeOrder = count;
                        if (videoLocalIDs.Count > 5)
                            xref.Percentage = 100;
                        else
                            xref.Percentage = GetEpisodePercentages(videoLocalIDs.Count)[count - 1];
                    }

                    repXRefs.Save(xref);

                    vid.RenameIfRequired();
                    vid.MoveFileIfRequired();

                    CommandRequest_WebCacheSendXRefFileEpisode cr = new CommandRequest_WebCacheSendXRefFileEpisode(xref.CrossRef_File_EpisodeID);
                    cr.Save();

                    count++;
                    if (!singleEpisode) epNumber++;
                }

                ser.QueueUpdateStats();

                // update epidsode added stats
                ser.EpisodeAddedDate = DateTime.Now;
                repSeries.Save(ser);

                AnimeGroupRepository repGroups = new AnimeGroupRepository();
                foreach (AnimeGroup grp in ser.AllGroupsAbove)
                {
                    grp.EpisodeAddedDate = DateTime.Now;
                    repGroups.Save(grp);
                }

            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }

            return "";
        }
		private void ProcessFile_AniDB(VideoLocal vidLocal)
		{
			logger.Trace("Checking for AniDB_File record for: {0} --- {1}", vidLocal.Hash, vidLocal.FilePath);
			// check if we already have this AniDB_File info in the database
			
			AniDB_FileRepository repAniFile = new AniDB_FileRepository();
			AniDB_EpisodeRepository repAniEps = new AniDB_EpisodeRepository();
			AniDB_AnimeRepository repAniAnime = new AniDB_AnimeRepository();
			AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
			VideoLocalRepository repVidLocals = new VideoLocalRepository();
			AnimeEpisodeRepository repEps = new AnimeEpisodeRepository();
			CrossRef_File_EpisodeRepository repXrefFE = new CrossRef_File_EpisodeRepository();

			AniDB_File aniFile = null;

			if (!ForceAniDB)
			{
				aniFile = repAniFile.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 = JMMService.AnidbProcessor.GetFileInfo(vidLocal);
				if (fileInfo != null)
				{
					// check if we already have a record
					aniFile = repAniFile.GetByHashAndFileSize(vidLocal.Hash, vlocal.FileSize);

					if (aniFile == null)
						aniFile = new AniDB_File();

					aniFile.Populate(fileInfo);

					//overwrite with local file name
					string localFileName = Path.GetFileName(vidLocal.FilePath);
					aniFile.FileName = localFileName;

					repAniFile.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 = repXrefFE.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)
					{
						crossRefs = XMLService.Get_CrossRef_File_Episode(vidLocal);
						if (crossRefs == null || crossRefs.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 (CrossRef_File_Episode xref in crossRefs)
							{
								// in this case we need to save the cross refs manually as AniDB did not provide them
								repXrefFE.Save(xref);
							}
						}
					}
					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 = repAniEps.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 = repAniEps.GetByEpisodeID(xref.EpisodeID);
						if (ep == null)
							missingEpisodes = true;

						animeID = xref.AnimeID;
					}
				}
			}

			// get from DB
			AniDB_Anime anime = repAniAnime.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....");

				// try using the cache first
				using (var session = JMMService.SessionFactory.OpenSession())
				{
					anime = JMMService.AnidbProcessor.GetAnimeInfoHTTPFromCache(session, animeID, ServerSettings.AutoGroupSeries);
				}

				// if not in cache try from AniDB
				if (anime == null)
					anime = JMMService.AnidbProcessor.GetAnimeInfoHTTP(animeID, true, ServerSettings.AutoGroupSeries);
			}

			// create the group/series/episode records if needed
			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 = repSeries.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
				AniDB_GroupStatusRepository repStatus = new AniDB_GroupStatusRepository();
				if (repStatus.GetByAnimeID(anime.AnimeID).Count == 0)
				{
					CommandRequest_GetReleaseGroupStatus cmdStatus = new CommandRequest_GetReleaseGroupStatus(anime.AnimeID, false);
					cmdStatus.Save();
				}

				// update stats
				ser.EpisodeAddedDate = DateTime.Now;
				repSeries.Save(ser);

				AnimeGroupRepository repGroups = new AnimeGroupRepository();
				foreach (AnimeGroup grp in ser.AllGroupsAbove)
				{
					grp.EpisodeAddedDate = DateTime.Now;
					repGroups.Save(grp);
				}
			}

			vidLocal.RenameIfRequired();
			vidLocal.MoveFileIfRequired();
			

			// update stats for groups and series
			if (ser != null)
			{
				// update all the groups above this series in the heirarchy
				ser.UpdateStats(true, true, true);
				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();
			}

			// lets also try adding to the users trakt collecion by sync'ing the series
			if (ser != null)
			{
				CommandRequest_TraktSyncCollectionSeries cmdTrakt = new CommandRequest_TraktSyncCollectionSeries(ser.AnimeSeriesID, ser.GetAnime().MainTitle);
				cmdTrakt.Save();
			}

			// sync the series on MAL
			if (ser != null)
			{
				CommandRequest_MALUpdatedWatchedStatus cmdMAL = new CommandRequest_MALUpdatedWatchedStatus(ser.AniDB_ID);
				cmdMAL.Save();
			}
		}
Example #18
0
		public void MoveFileIfRequired()
		{
            try
            {
                logger.Trace("Attempting to move file: {0}", this.FullServerPath);

                // check if this file is in the drop folder
                // otherwise we don't need to move it
                if (this.ImportFolder.IsDropSource == 0)
                {
                    logger.Trace("Not moving file as it is NOT in the drop folder: {0}", this.FullServerPath);
                    return;
                }

                if (!File.Exists(this.FullServerPath))
                {
                    logger.Error("Could not find the file to move: {0}", this.FullServerPath);
                    return;
                }

                // find the default destination
                ImportFolder destFolder = null;
                ImportFolderRepository repFolders = new ImportFolderRepository();
                foreach (ImportFolder fldr in repFolders.GetAll())
                {
                    if (fldr.IsDropDestination == 1)
                    {
                        destFolder = fldr;
                        break;
                    }
                }

                if (destFolder == null) return;

                if (!Directory.Exists(destFolder.ImportFolderLocation)) return;

                // keep the original drop folder for later (take a copy, not a reference)
                ImportFolder dropFolder = this.ImportFolder;

                // we can only move the file if it has an anime associated with it
                List<CrossRef_File_Episode> xrefs = this.EpisodeCrossRefs;
                if (xrefs.Count == 0) return;
                CrossRef_File_Episode xref = xrefs[0];

                // find the series associated with this episode
                AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
                AnimeSeries series = repSeries.GetByAnimeID(xref.AnimeID);
                if (series == null) return;

                // find where the other files are stored for this series
                // if there are no other files except for this one, it means we need to create a new location
                bool foundLocation = false;
                string newFullPath = "";

                // sort the episodes by air date, so that we will move the file to the location of the latest episode
                List<AnimeEpisode> allEps = series.GetAnimeEpisodes();
                List<SortPropOrFieldAndDirection> sortCriteria = new List<SortPropOrFieldAndDirection>();
                sortCriteria.Add(new SortPropOrFieldAndDirection("AniDB_EpisodeID", true, SortType.eInteger));
                allEps = Sorting.MultiSort<AnimeEpisode>(allEps, sortCriteria);

                AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();
                CrossRef_File_EpisodeRepository repFileEpXref = new CrossRef_File_EpisodeRepository();

                foreach (AnimeEpisode ep in allEps)
                {
                    // check if this episode belongs to more than one anime
                    // if it does we will ignore it
                    List<CrossRef_File_Episode> fileEpXrefs = repFileEpXref.GetByEpisodeID(ep.AniDB_EpisodeID);
                    int? animeID = null;
                    bool crossOver = false;
                    foreach (CrossRef_File_Episode fileEpXref in fileEpXrefs)
                    {
                        if (!animeID.HasValue)
                            animeID = fileEpXref.AnimeID;
                        else
                        {
                            if (animeID.Value != fileEpXref.AnimeID)
                                crossOver = true;
                        }
                    }
                    if (crossOver) continue;

                    foreach (VideoLocal vid in ep.GetVideoLocals())
                    {
                        if (vid.VideoLocalID != this.VideoLocalID)
                        {
                            // make sure this folder is not the drop source
                            if (vid.ImportFolder.IsDropSource == 1) continue;

                            string thisFileName = vid.FullServerPath;
                            string folderName = Path.GetDirectoryName(thisFileName);

                            if (Directory.Exists(folderName))
                            {
                                newFullPath = folderName;
                                foundLocation = true;
                                break;
                            }
                        }
                    }
                    if (foundLocation) break;
                }

                if (!foundLocation)
                {
                    // we need to create a new folder
                    string newFolderName = Utils.RemoveInvalidFolderNameCharacters(series.GetAnime().MainTitle);
                    newFullPath = Path.Combine(destFolder.ImportFolderLocation, newFolderName);
                    if (!Directory.Exists(newFullPath))
                        Directory.CreateDirectory(newFullPath);
                }

                int newFolderID = 0;
                string newPartialPath = "";
                string newFullServerPath = Path.Combine(newFullPath, Path.GetFileName(this.FullServerPath));

                DataAccessHelper.GetShareAndPath(newFullServerPath, repFolders.GetAll(), ref newFolderID, ref newPartialPath);
                logger.Info("Moving file from {0} to {1}", this.FullServerPath, newFullServerPath);

                if (File.Exists(newFullServerPath))
                {
                    logger.Trace("Not moving file as it already exists at the new location, deleting source file instead: {0} --- {1}", 
                        this.FullServerPath, newFullServerPath);

                    // if the file already exists, we can just delete the source file instead
                    // this is safer than deleting and moving
                    File.Delete(this.FullServerPath);

                    this.ImportFolderID = newFolderID;
                    this.FilePath = newPartialPath;
                    VideoLocalRepository repVids = new VideoLocalRepository();
                    repVids.Save(this);
                }
                else
                {
                    string originalFileName = this.FullServerPath;
                    FileInfo fi = new FileInfo(originalFileName);

                    // now move the file
                    File.Move(this.FullServerPath, newFullServerPath);

                    this.ImportFolderID = newFolderID;
                    this.FilePath = newPartialPath;
                    VideoLocalRepository repVids = new VideoLocalRepository();
                    repVids.Save(this);

                    try
                    {
                        // move any subtitle files
                        foreach (string subtitleFile in Utils.GetPossibleSubtitleFiles(originalFileName))
                        {
                            if (File.Exists(subtitleFile))
                            {
                                FileInfo fiSub = new FileInfo(subtitleFile);
                                string newSubPath = Path.Combine(Path.GetDirectoryName(newFullServerPath), fiSub.Name);
                                if (File.Exists(newSubPath))
                                {
                                    // if the file already exists, we can just delete the source file instead
                                    // this is safer than deleting and moving
                                    File.Delete(newSubPath);
                                }
                                else
                                    File.Move(subtitleFile, newSubPath);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorException(ex.ToString(), ex);
                    }

                    // check for any empty folders in drop folder
                    // only for the drop folder
                    if (dropFolder.IsDropSource == 1)
                    {
                        foreach (string folderName in Directory.GetDirectories(dropFolder.ImportFolderLocation, "*", SearchOption.AllDirectories))
                        {
                            if (Directory.Exists(folderName))
                            {
                                if (Directory.GetFiles(folderName, "*", SearchOption.AllDirectories).Length == 0)
                                {
                                    try
                                    {
                                        Directory.Delete(folderName, true);
                                    }
                                    catch (Exception ex)
                                    {
                                        logger.ErrorException(ex.ToString(), ex);
                                    }
                                }
                            }
                        }
                    }

                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("Could not move file: {0} -- {1}", this.FullServerPath, ex.ToString());
                logger.ErrorException(msg, ex);
            }

        }