Пример #1
0
 public void Populate(CrossRef_File_Episode cfe)
 {
     this.FileName   = cfe.FileName;
     this.FileSize   = cfe.FileSize;
     this.Hash       = cfe.Hash;
     DateTimeUpdated = DateTime.Now;
 }
Пример #2
0
 public void Populate(CrossRef_File_Episode cfe)
 {
     this.FileName = cfe.FileName;
     this.FileSize = cfe.FileSize;
     this.Hash = cfe.Hash;
     DateTimeUpdated = DateTime.Now;
 }
Пример #3
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);
                        }
                    }
                }
            }
        }
Пример #4
0
        public static void Send_CrossRefFileEpisode(JMMServer.Entities.CrossRef_File_Episode data)
        {
            if (!ServerSettings.WebCache_XRefFileEpisode_Send)
            {
                return;
            }

            string uri = string.Format(@"http://{0}/api/CrossRef_File_Episode", azureHostBaseAddress);

            CrossRef_File_EpisodeInput input = new CrossRef_File_EpisodeInput(data);
            string json = JSONHelper.Serialize <CrossRef_File_EpisodeInput>(input);

            SendData(uri, json, "POST");
        }
Пример #5
0
		// default constructor
		public CrossRef_File_EpisodeRequest(CrossRef_File_Episode data)
		{
			this.AnimeID = data.AnimeID;
			this.EpisodeID = data.EpisodeID;
			this.Percentage = data.Percentage;
			this.EpisodeOrder = data.EpisodeOrder;
			this.hash = data.Hash;

			string username = ServerSettings.AniDB_Username;
			if (ServerSettings.WebCache_Anonymous)
				username = Constants.AnonWebCacheUsername;

			this.uname = username;
		}
		public void Save(CrossRef_File_Episode obj)
		{
			using (var session = JMMService.SessionFactory.OpenSession())
			{
				// populate the database
				using (var transaction = session.BeginTransaction())
				{
					session.SaveOrUpdate(obj);
					transaction.Commit();
				}
			}
			logger.Trace("Updating group stats by file from CrossRef_File_EpisodeRepository.Save: {0}", obj.Hash);
			StatsCache.Instance.UpdateUsingAniDBFile(obj.Hash);
		}
Пример #7
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);
						}
					}
				}
			}
		}
Пример #8
0
		/// <summary>
		/// Current only handling one file containing file
		/// </summary>
		/// <param name="vid"></param>
		/// <returns></returns>
		public static List<CrossRef_File_Episode> Get_CrossRef_File_Episode(VideoLocal vid)
		{
			List<CrossRef_File_Episode> crossRefs = new List<CrossRef_File_Episode>();

			if (!ServerSettings.WebCache_XRefFileEpisode_Get) return null;

			try
			{
				string username = ServerSettings.AniDB_Username;
				if (ServerSettings.WebCache_Anonymous)
					username = Constants.AnonWebCacheUsername;

				string uri = string.Format("http://{0}/GetCrossRef_File_Episode.aspx?uname={1}&hash={2}",
					ServerSettings.WebCache_Address, username, vid.Hash);
				string xml = GetData(uri);

				if (xml.Trim().Length == 0) return null;

				XmlDocument docFile = new XmlDocument();
				docFile.LoadXml(xml);

				string sAnimeID = TryGetProperty(docFile, "CrossRef_File_EpisodeResultCollection", "AnimeID").ToUpper();
				string sEpisodeID = TryGetProperty(docFile, "CrossRef_File_EpisodeResultCollection", "EpisodeIDs").ToUpper();
				string sEpisodeOrder = TryGetProperty(docFile, "CrossRef_File_EpisodeResultCollection", "EpisodeOrders").ToUpper();
				string sPercentages = TryGetProperty(docFile, "CrossRef_File_EpisodeResultCollection", "EpisodePercentages").ToUpper();

				int animeID = 0;
				int.TryParse(sAnimeID, out animeID);

				if (animeID <= 0) return null;

				string[] epids = sEpisodeID.Split('|');
				string[] eporders = sEpisodeOrder.Split('|');
				string[] eppcts = sPercentages.Split('|');

				for (int i=0;i < epids.Length; i++)
				{
					int episodeID = 0, percentage = 0, episodeOrder = 0;

					int.TryParse(epids[i], out episodeID);
					int.TryParse(eporders[i], out episodeOrder);
					int.TryParse(eppcts[i], out percentage);

					CrossRef_File_Episode xref = new CrossRef_File_Episode();
					xref.Hash = vid.ED2KHash;
					xref.FileName = Path.GetFileName(vid.FullServerPath);
					xref.FileSize = vid.FileSize;
					xref.CrossRefSource = (int)JMMServer.CrossRefSource.WebCache;
					xref.AnimeID = animeID;
					xref.EpisodeID = episodeID;
					xref.Percentage = percentage;
					xref.EpisodeOrder = episodeOrder;

					crossRefs.Add(xref);
				}

				

				return crossRefs;
			}
			catch (Exception ex)
			{
				logger.ErrorException("Error in XMLService.Get_FileHash:: {0}", ex);
				return null;
			}
		}
Пример #9
0
		public static void Send_CrossRef_File_Episode(CrossRef_File_Episode data)
		{
			if (!ServerSettings.WebCache_XRefFileEpisode_Send) return;


			string uri = string.Format("http://{0}/AddCrossRef_File_Episode.aspx", ServerSettings.WebCache_Address);
			CrossRef_File_EpisodeRequest fhr = new CrossRef_File_EpisodeRequest(data);
			string xml = fhr.ToXML();

			SendData(uri, xml);
		}
Пример #10
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 "";
        }
Пример #11
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 "";
        }
Пример #12
0
        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)
                    {
                        List<JMMServer.Providers.Azure.CrossRef_File_Episode> xrefs = JMMServer.Providers.Azure.AzureWebAPI.Get_CrossRefFileEpisode(vidLocal);

                        crossRefs = new List<CrossRef_File_Episode>();
                        if (xrefs == null || xrefs.Count == 0)
                        {
                            logger.Debug("Cannot find AniDB_File record or get cross ref from web cache record so exiting: {0}", vidLocal.ED2KHash);
                            return;
                        }
                        else
                        {
                            foreach (JMMServer.Providers.Azure.CrossRef_File_Episode xref in xrefs)
                            {
                                CrossRef_File_Episode xrefEnt = new CrossRef_File_Episode();
                                xrefEnt.Hash = vidLocal.ED2KHash;
                                xrefEnt.FileName = Path.GetFileName(vidLocal.FullServerPath);
                                xrefEnt.FileSize = vidLocal.FileSize;
                                xrefEnt.CrossRefSource = (int)JMMServer.CrossRefSource.WebCache;
                                xrefEnt.AnimeID = animeID;
                                xrefEnt.EpisodeID = xref.EpisodeID;
                                xrefEnt.Percentage = xref.Percentage;
                                xrefEnt.EpisodeOrder = xref.EpisodeOrder;

                                crossRefs.Add(xrefEnt);
                                // in this case we need to save the cross refs manually as AniDB did not provide them
                                repXrefFE.Save(xrefEnt);
                            }
                        }
                    }
                    else
                    {
                        logger.Debug("Cannot get AniDB_File record so exiting: {0}", vidLocal.ED2KHash);
                        return;
                    }
                }

                // we assume that all episodes belong to the same anime
                foreach (CrossRef_File_Episode xref in crossRefs)
                {
                    animeID = xref.AnimeID;

                    AniDB_Episode ep = 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....");
                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.QueueUpdateStats();
                //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID);
            }

            // Add this file to the users list
            if (ServerSettings.AniDB_MyList_AddFiles)
            {
                CommandRequest_AddFileToMyList cmd = new CommandRequest_AddFileToMyList(vidLocal.ED2KHash);
                cmd.Save();
            }
        }
Пример #13
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 "";
        }
Пример #14
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();
                            JMMServer.Entities.CrossRef_File_Episode xref = new JMMServer.Entities.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.QueueUpdateStats();
								//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);
			}
		}
Пример #15
0
        public void MoveFileIfRequired()
        {
            // check if this file is in the drop folder
            // otherwise we don't need to move it
            if (this.ImportFolder.IsDropSource == 0)
            {
                return;
            }

            if (!File.Exists(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;
            }

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

            foreach (AnimeEpisode ep in allEps)
            {
                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))
            {
                // 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 (this.ImportFolder.IsDropSource == 1)
                {
                    foreach (string folderName in Directory.GetDirectories(this.ImportFolder.ImportFolderLocation, "*", SearchOption.AllDirectories))
                    {
                        if (Directory.Exists(folderName))
                        {
                            if (Directory.GetFiles(folderName, "*", SearchOption.AllDirectories).Length == 0)
                            {
                                try
                                {
                                    Directory.Delete(folderName, true);
                                }

                                /*catch (IOException)
                                 * {
                                 *      Thread.Sleep(0);
                                 *      Directory.Delete(folderName, false);
                                 * }*/
                                catch (Exception ex)
                                {
                                    logger.ErrorException(ex.ToString(), ex);
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #16
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 (!System.IO.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().OrderByDescending(a => a.AniDB_EpisodeID).ToList();

                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().PreferredTitle);
                    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, true);
                }
                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, true);

                    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);
            }
        }
Пример #17
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 (ImportFolder.IsDropSource == 0)
                {
                    logger.Trace("Not moving file as it is NOT in the drop folder: {0}", this.FullServerPath);
                    return;
                }
                IFileSystem f = this.ImportFolder.FileSystem;
                if (f == null)
                {
                    logger.Trace("Unable to MOVE, filesystem not working: {0}", this.FullServerPath);
                    return;
                }

                FileSystemResult <IObject> fsrresult = f.Resolve(FullServerPath);
                if (!fsrresult.IsOk)
                {
                    logger.Error("Could not find the file to move: {0}", this.FullServerPath);
                    return;
                }
                IFile source_file = fsrresult.Result as IFile;
                if (source_file == null)
                {
                    logger.Error("Could not find the file to move: {0}", this.FullServerPath);
                    return;
                }
                // find the default destination
                ImportFolder destFolder = null;
                foreach (ImportFolder fldr in RepoFactory.ImportFolder.GetAll().Where(a => a.CloudID == ImportFolder.CloudID))
                {
                    if (fldr.IsDropDestination == 1)
                    {
                        destFolder = fldr;
                        break;
                    }
                }

                if (destFolder == null)
                {
                    return;
                }

                FileSystemResult <IObject> re = f.Resolve(destFolder.ImportFolderLocation);
                if (!re.IsOk)
                {
                    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.VideoLocal.EpisodeCrossRefs;
                if (xrefs.Count == 0)
                {
                    return;
                }
                CrossRef_File_Episode xref = xrefs[0];

                // find the series associated with this episode
                AnimeSeries series = RepoFactory.AnimeSeries.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().OrderByDescending(a => a.AniDB_EpisodeID).ToList();

                IDirectory destination = null;

                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 = RepoFactory.CrossRef_File_Episode.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().Where(a => a.Places.Any(b => b.ImportFolder.CloudID == destFolder.CloudID && b.ImportFolder.IsDropSource == 0)))
                    {
                        if (vid.VideoLocalID != this.VideoLocalID)
                        {
                            VideoLocal_Place place        = vid.Places.FirstOrDefault(a => a.ImportFolder.CloudID == destFolder.CloudID);
                            string           thisFileName = place?.FullServerPath;
                            string           folderName   = Path.GetDirectoryName(thisFileName);

                            FileSystemResult <IObject> dir = f.Resolve(folderName);
                            if (dir.IsOk)
                            {
                                destination   = (IDirectory)dir.Result;
                                newFullPath   = folderName;
                                foundLocation = true;
                                break;
                            }
                        }
                    }
                    if (foundLocation)
                    {
                        break;
                    }
                }

                if (!foundLocation)
                {
                    // we need to create a new folder
                    string newFolderName = Utils.RemoveInvalidFolderNameCharacters(series.GetAnime().PreferredTitle);

                    newFullPath = Path.Combine(destFolder.ParsedImportFolderLocation, newFolderName);
                    FileSystemResult <IObject> dirn = f.Resolve(newFullPath);
                    if (!dirn.IsOk)
                    {
                        dirn = f.Resolve(destFolder.ImportFolderLocation);
                        if (dirn.IsOk)
                        {
                            IDirectory d = (IDirectory)dirn.Result;
                            FileSystemResult <IDirectory> d2 = Task.Run(async() => await d.CreateDirectoryAsync(newFolderName, null)).Result;
                            destination = d2.Result;
                        }
                    }
                    else if (dirn.Result is IFile)
                    {
                        logger.Error("Destination folder is a file: {0}", newFolderName);
                    }
                    else
                    {
                        destination = (IDirectory)dirn.Result;
                    }
                }

                string newFullServerPath         = Path.Combine(newFullPath, Path.GetFileName(this.FullServerPath));
                Tuple <ImportFolder, string> tup = VideoLocal_PlaceRepository.GetFromFullPath(newFullServerPath);
                if (tup == null)
                {
                    logger.Error($"Unable to LOCATE file {newFullServerPath} inside the import folders");
                    return;
                }

                logger.Info("Moving file from {0} to {1}", this.FullServerPath, newFullServerPath);

                FileSystemResult <IObject> dst = f.Resolve(newFullServerPath);
                if (dst.IsOk)
                {
                    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
                    FileSystemResult fr = new FileSystemResult();
                    try
                    {
                        fr = source_file.Delete(false);
                        if (!fr.IsOk)
                        {
                            logger.Warn("Unable to DELETE file: {0} error {1}", this.FullServerPath, fr?.Error ?? String.Empty);
                        }
                        this.ImportFolderID = tup.Item1.ImportFolderID;
                        this.FilePath       = tup.Item2;
                        RepoFactory.VideoLocalPlace.Save(this);

                        // check for any empty folders in drop folder
                        // only for the drop folder
                        if (dropFolder.IsDropSource == 1)
                        {
                            FileSystemResult <IObject> dd = f.Resolve(dropFolder.ImportFolderLocation);
                            if (dd != null && dd.IsOk && dd.Result is IDirectory)
                            {
                                RecursiveDeleteEmptyDirectories((IDirectory)dd.Result, true);
                            }
                        }
                    }
                    catch
                    {
                        logger.Error("Unable to DELETE file: {0} error {1}", this.FullServerPath, fr?.Error ?? String.Empty);
                    }
                }
                else
                {
                    FileSystemResult fr = source_file.Move(destination);
                    if (!fr.IsOk)
                    {
                        logger.Error("Unable to MOVE file: {0} to {1} error {2)", this.FullServerPath, newFullServerPath, fr?.Error ?? String.Empty);
                        return;
                    }
                    string originalFileName = this.FullServerPath;


                    this.ImportFolderID = tup.Item1.ImportFolderID;
                    this.FilePath       = tup.Item2;
                    RepoFactory.VideoLocalPlace.Save(this);

                    try
                    {
                        // move any subtitle files
                        foreach (string subtitleFile in Utils.GetPossibleSubtitleFiles(originalFileName))
                        {
                            FileSystemResult <IObject> src = f.Resolve(subtitleFile);
                            if (src.IsOk && src.Result is IFile)
                            {
                                string newSubPath = Path.Combine(Path.GetDirectoryName(newFullServerPath), ((IFile)src.Result).Name);
                                dst = f.Resolve(newSubPath);
                                if (dst.IsOk && dst.Result is IFile)
                                {
                                    FileSystemResult fr2 = src.Result.Delete(true);
                                    if (!fr2.IsOk)
                                    {
                                        logger.Warn("Unable to DELETE file: {0} error {1}", subtitleFile,
                                                    fr2?.Error ?? String.Empty);
                                    }
                                }
                                else
                                {
                                    FileSystemResult fr2 = ((IFile)src.Result).Move(destination);
                                    if (!fr2.IsOk)
                                    {
                                        logger.Error("Unable to MOVE file: {0} to {1} error {2)", subtitleFile,
                                                     newSubPath, fr2?.Error ?? String.Empty);
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex, ex.ToString());
                    }

                    // check for any empty folders in drop folder
                    // only for the drop folder
                    if (dropFolder.IsDropSource == 1)
                    {
                        FileSystemResult <IObject> dd = f.Resolve(dropFolder.ImportFolderLocation);
                        if (dd != null && dd.IsOk && dd.Result is IDirectory)
                        {
                            RecursiveDeleteEmptyDirectories((IDirectory)dd.Result, true);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = $"Could not MOVE file: {this.FullServerPath} -- {ex.ToString()}";
                logger.Error(ex, msg);
            }
        }
        public string AssociateMultipleFiles(List<int> videoLocalIDs, int animeSeriesID, int startingEpisodeNumber,
            bool singleEpisode)
        {
            try
            {

                AnimeSeries ser = RepoFactory.AnimeSeries.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 = RepoFactory.VideoLocal.GetByID(videoLocalID);
                    if (vid == null)
                        return "Could not find video local record";
                    if (vid.Hash == null)
                        return "Could not associate a cloud file without hash, hash it locally first";

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

                    AniDB_Episode aniep = anieps[0];

                    AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(aniep.EpisodeID);
                    if (ep == null)
                        return "Could not find episode record";

                    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];
                    }

                    RepoFactory.CrossRef_File_Episode.Save(xref);
                    CommandRequest_WebCacheSendXRefFileEpisode cr =
                        new CommandRequest_WebCacheSendXRefFileEpisode(xref.CrossRef_File_EpisodeID);
                    cr.Save();
                    vid.Places.ForEach(a =>
                    {
                        a.RenameIfRequired();
                        a.MoveFileIfRequired();

                    });
                    count++;
                    if (!singleEpisode) epNumber++;
                }
                ser.EpisodeAddedDate = DateTime.Now;
                RepoFactory.AnimeSeries.Save(ser, false, true);

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

                // update epidsode added stats
                ser.QueueUpdateStats();
            }
            catch (Exception ex)
            {
                logger.Error( ex,ex.ToString());
            }

            return "";
        }
        public string AssociateSingleFileWithMultipleEpisodes(int videoLocalID, int animeSeriesID, int startEpNum,
            int endEpNum)
        {
            try
            {
                VideoLocal vid = RepoFactory.VideoLocal.GetByID(videoLocalID);
                if (vid == null)
                    return "Could not find video record";
                if (vid.Hash == null)
                    return "Could not associate a cloud file without hash, hash it locally first";
                AnimeSeries ser = RepoFactory.AnimeSeries.GetByID(animeSeriesID);
                if (ser == null)
                    return "Could not find anime series record";
                for (int i = startEpNum; i <= endEpNum; i++)
                {
                    List<AniDB_Episode> anieps = RepoFactory.AniDB_Episode.GetByAnimeIDAndEpisodeNumber(ser.AniDB_ID, i);
                    if (anieps.Count == 0)
                        return "Could not find the AniDB episode record";

                    AniDB_Episode aniep = anieps[0];

                    AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(aniep.EpisodeID);
                    if (ep == null)
                        return "Could not find episode record";

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

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

                }
                vid.Places.ForEach(a =>
                {
                    a.RenameIfRequired();
                    a.MoveFileIfRequired();
                });
                ser.EpisodeAddedDate = DateTime.Now;
                RepoFactory.AnimeSeries.Save(ser, false, true);

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

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

                return "";
            }
            catch (Exception ex)
            {
                logger.Error( ex,ex.ToString());
            }

            return "";
        }
        public string AssociateSingleFile(int videoLocalID, int animeEpisodeID)
        {
            try
            {
                VideoLocal vid = RepoFactory.VideoLocal.GetByID(videoLocalID);
                if (vid == null)
                    return "Could not find video record";
                if (string.IsNullOrEmpty(vid.Hash))
                    return "Could not associate a cloud file without hash, hash it locally first";

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

                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;
                }
                RepoFactory.CrossRef_File_Episode.Save(xref);
                CommandRequest_WebCacheSendXRefFileEpisode cr = new CommandRequest_WebCacheSendXRefFileEpisode(xref.CrossRef_File_EpisodeID);
                cr.Save();
                vid.Places.ForEach(a =>
                {
                    a.RenameIfRequired();
                    a.MoveFileIfRequired();
                });

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

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

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

                CommandRequest_AddFileToMyList cmdAddFile = new CommandRequest_AddFileToMyList(vid.Hash);
                cmdAddFile.Save();
                return "";
            }
            catch (Exception ex)
            {
                logger.Error( ex,ex.ToString());
            }

            return "";
        }