public Contract_AniDB_Anime_Relation ToContract(AniDB_Anime anime, AnimeSeries ser, int userID) { Contract_AniDB_Anime_Relation contract = new Contract_AniDB_Anime_Relation(); contract.AniDB_Anime_RelationID = this.AniDB_Anime_RelationID; contract.AnimeID = this.AnimeID; contract.RelationType = this.RelationType; contract.RelatedAnimeID = this.RelatedAnimeID; contract.AniDB_Anime = anime?.Contract?.AniDBAnime; contract.AnimeSeries = ser?.GetUserContract(userID); return(contract); }
/// <summary> /// Returns whether a user is allowed to view this series /// </summary> /// <param name="ser"></param> /// <returns></returns> public bool AllowedSeries(ISession session, AnimeSeries ser) { if (string.IsNullOrEmpty(HideCategories)) { return(true); } string[] cats = HideCategories.ToLower().Split(','); string[] animeCats = ser.GetAnime(session).AllCategories.ToLower().Split('|'); foreach (string cat in cats) { if (!string.IsNullOrEmpty(cat) && animeCats.Contains(cat)) { return(false); } } return(true); }
public Contract_AniDB_Anime_Relation ToContract(AniDB_Anime anime, AnimeSeries ser, int userID) { Contract_AniDB_Anime_Relation contract = new Contract_AniDB_Anime_Relation(); contract.AniDB_Anime_RelationID = this.AniDB_Anime_RelationID; contract.AnimeID = this.AnimeID; contract.RelationType = this.RelationType; contract.RelatedAnimeID = this.RelatedAnimeID; contract.AniDB_Anime = null; if (anime != null) { contract.AniDB_Anime = anime.ToContract(); } contract.AnimeSeries = null; if (ser != null) { contract.AnimeSeries = ser.ToContract(ser.GetUserRecord(userID)); } return(contract); }
public Contract_AniDB_Anime_Similar ToContract(AniDB_Anime anime, AnimeSeries ser, int userID) { Contract_AniDB_Anime_Similar contract = new Contract_AniDB_Anime_Similar(); contract.AniDB_Anime_SimilarID = this.AniDB_Anime_SimilarID; contract.AnimeID = this.AnimeID; contract.SimilarAnimeID = this.SimilarAnimeID; contract.Approval = this.Approval; contract.Total = this.Total; contract.AniDB_Anime = null; if (anime != null) { contract.AniDB_Anime = anime.ToContract(); } contract.AnimeSeries = null; if (ser != null) { contract.AnimeSeries = ser.ToContract(ser.GetUserRecord(userID)); } return(contract); }
public void ToggleWatchedStatus(bool watched, bool updateOnline, DateTime?watchedDate, bool updateStats, bool updateStatsCache, int userID, bool syncTrakt, bool updateWatchedDate) { JMMUser user = RepoFactory.JMMUser.GetByID(userID); if (user == null) { return; } List <JMMUser> aniDBUsers = RepoFactory.JMMUser.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 = RepoFactory.AniDB_File.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; } RepoFactory.AniDB_File.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 = RepoFactory.CrossRef_File_Episode.GetByHash(this.Hash); Dictionary <int, AnimeSeries> toUpdateSeries = new Dictionary <int, AnimeSeries>(); 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 episodes for this file, may be more than one (One Piece x Toriko) AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(xref.EpisodeID); // 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 && vidUser.WatchedDate.HasValue) { // if not null means it is watched epPercentWatched += filexref.Percentage; } if (epPercentWatched > 95) { break; } } if (epPercentWatched > 95) { ser = ep.GetAnimeSeries(); if (!toUpdateSeries.ContainsKey(ser.AnimeSeriesID)) { toUpdateSeries.Add(ser.AnimeSeriesID, ser); } 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 (syncTrakt && ServerSettings.Trakt_IsEnabled && !string.IsNullOrEmpty(ServerSettings.Trakt_AuthToken)) { CommandRequest_TraktHistoryEpisode cmdSyncTrakt = new CommandRequest_TraktHistoryEpisode(ep.AnimeEpisodeID, TraktSyncAction.Add); cmdSyncTrakt.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) { // get the episodes for this file, may be more than one (One Piece x Toriko) AnimeEpisode ep = RepoFactory.AnimeEpisode.GetByAniDBEpisodeID(xrefEp.EpisodeID); ser = ep.GetAnimeSeries(); if (!toUpdateSeries.ContainsKey(ser.AnimeSeriesID)) { toUpdateSeries.Add(ser.AnimeSeriesID, ser); } // 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 && vidUser.WatchedDate.HasValue) { 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); } } } if (syncTrakt && ServerSettings.Trakt_IsEnabled && !string.IsNullOrEmpty(ServerSettings.Trakt_AuthToken)) { CommandRequest_TraktHistoryEpisode cmdSyncTrakt = new CommandRequest_TraktHistoryEpisode(ep.AnimeEpisodeID, TraktSyncAction.Remove); cmdSyncTrakt.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 (toUpdateSeries.Count > 0 && updateStats) { foreach (AnimeSeries s in toUpdateSeries.Values) { // update all the groups above this series in the heirarchy s.UpdateStats(true, true, true); } //ser.TopLevelAnimeGroup.UpdateStatsFromTopLevel(true, true, true); } //if (ser != null && updateStatsCache) //StatsCache.Instance.UpdateUsingSeries(ser.AnimeSeriesID); }
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); } } } } } } }
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); } }
public static List <AnimeGroup> GetRelatedGroupsFromAnimeID(ISession session, int animeid) { // TODO we need to recusrive list at all relations and not just the first one AniDB_AnimeRepository repAniAnime = new AniDB_AnimeRepository(); AnimeSeriesRepository repSeries = new AnimeSeriesRepository(); AnimeGroupRepository repGroups = new AnimeGroupRepository(); List <AnimeGroup> grps = new List <AnimeGroup>(); AniDB_Anime anime = repAniAnime.GetByAnimeID(session, animeid); if (anime == null) { return(grps); } // first check for groups which are directly related List <AniDB_Anime_Relation> relations = anime.GetRelatedAnime(session); foreach (AniDB_Anime_Relation rel in relations) { string relationtype = rel.RelationType.ToLower(); if ((relationtype == "same setting") || (relationtype == "alternative setting") || (relationtype == "character") || (relationtype == "other")) { //Filter these relations these will fix messes, like Gundam , Clamp, etc. continue; } // we actually need to get the series, because it might have been added to another group already AnimeSeries ser = repSeries.GetByAnimeID(session, rel.RelatedAnimeID); if (ser != null) { AnimeGroup grp = repGroups.GetByID(session, ser.AnimeGroupID); if (grp != null) { grps.Add(grp); } } } if (grps.Count > 0) { return(grps); } // if nothing found check by all related anime List <AniDB_Anime> relatedAnime = anime.GetAllRelatedAnime(session); foreach (AniDB_Anime rel in relatedAnime) { // we actually need to get the series, because it might have been added to another group already AnimeSeries ser = repSeries.GetByAnimeID(session, rel.AnimeID); if (ser != null) { AnimeGroup grp = repGroups.GetByID(session, ser.AnimeGroupID); if (grp != null) { grps.Add(grp); } } } return(grps); }
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 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); } }