public List<EDSMSystem> GetSystemNames(bool resetLocal) { List<EDSMSystem> systemNames = new List<EDSMSystem>(); var localFile = new FileInfo(Path.Combine(Environment.CurrentDirectory, edsmDataFileName)); if (!resetLocal && localFile.Exists) { using (StreamReader r = new StreamReader(localFile.FullName)) { string json = r.ReadToEnd(); systemNames = JsonConvert.DeserializeObject<List<EDSMSystem>>(json); } } else { using (WebClient wc = new WebClient()) { var json = wc.DownloadString("http://www.edsm.net/api-v1/systems"); systemNames = JsonConvert.DeserializeObject<List<EDSMSystem>>(json); // save to local file. if (localFile.Exists) { localFile.Delete(true); } using ( StreamWriter outputFile = new StreamWriter(Path.Combine(Environment.CurrentDirectory.ToString(), edsmDataFileName))) { outputFile.WriteLine(JsonConvert.SerializeObject(systemNames)); } } } return systemNames; }
private static ItemMissing UpdateMissingItem([NotNull] ItemMissing me, [NotNull] FileInfo dce, int epF, int maxEp, int seasF) { if (me.Episode.Show is null) { return(me); } ShowRule sr = new ShowRule { DoWhatNow = RuleAction.kMerge, First = epF, Second = maxEp }; me.Episode.Show?.AddSeasonRule(seasF, sr); LOGGER.Info( $"Looking at {me.Episode.Show.ShowName} and have identified that episode {epF} and {maxEp} of season {seasF} have been merged into one file {dce.FullName}"); LOGGER.Info($"Added new rule automatically for {sr}"); //Regenerate the episodes with the new rule added ShowLibrary.GenerateEpisodeDict(me.Episode.Show); //Get the newly created processed episode we are after // ReSharper disable once InconsistentNaming ProcessedEpisode newPE = me.Episode; foreach (ProcessedEpisode pe in me.Episode.Show.SeasonEpisodes[seasF]) { if (pe.AppropriateEpNum == epF && pe.EpNum2 == maxEp) { newPE = pe; } } return(new ItemMissing(newPE, me.TargetFolder)); }
public override ItemList ProcessShow(ShowItem si, bool forceRefresh) { // for each tv show, optionally write a tvshow.nfo file if (TVSettings.Instance.NFOShows) { ItemList TheActionList = new ItemList(); FileInfo tvshownfo = FileHelper.FileInFolder(si.AutoAdd_FolderBase, "tvshow.nfo"); bool needUpdate = !tvshownfo.Exists || (si.TheSeries().Srv_LastUpdated > TimeZone.Epoch(tvshownfo.LastWriteTime)) || // was it written before we fixed the bug in <episodeguideurl> ? (tvshownfo.LastWriteTime.ToUniversalTime().CompareTo(new DateTime(2009, 9, 13, 7, 30, 0, 0, DateTimeKind.Utc)) < 0); bool alreadyOnTheList = DownloadKODIMetaData.doneNFO.Contains(tvshownfo.FullName); if ((forceRefresh || needUpdate) && !alreadyOnTheList) { TheActionList.Add(new ActionNFO(tvshownfo, si)); DownloadKODIMetaData.doneNFO.Add(tvshownfo.FullName); } return(TheActionList); } return(base.ProcessShow(si, forceRefresh)); }
private void AlphaFS_File_CreateSymbolicLink_And_GetLinkTargetInfo(bool isNetwork) { using (var tempRoot = new TemporaryDirectory(isNetwork)) { var fileLink = System.IO.Path.Combine(tempRoot.Directory.FullName, "FileLink-ToOriginalFile.txt"); var fileInfo = new System.IO.FileInfo(System.IO.Path.Combine(tempRoot.Directory.FullName, "OriginalFile.txt")); using (fileInfo.CreateText()) {} Console.WriteLine("Input File Path: [{0}]", fileInfo.FullName); Console.WriteLine("Input File Link: [{0}]", fileLink); Alphaleonis.Win32.Filesystem.File.CreateSymbolicLink(fileLink, fileInfo.FullName); var lvi = Alphaleonis.Win32.Filesystem.File.GetLinkTargetInfo(fileLink); UnitTestConstants.Dump(lvi); Assert.IsTrue(lvi.PrintName.Equals(fileInfo.FullName, StringComparison.OrdinalIgnoreCase)); UnitTestConstants.Dump(new System.IO.FileInfo(fileLink)); var alphaFSFileInfo = new Alphaleonis.Win32.Filesystem.FileInfo(fileLink); UnitTestConstants.Dump(alphaFSFileInfo.EntryInfo); Assert.AreEqual(System.IO.File.Exists(alphaFSFileInfo.FullName), alphaFSFileInfo.Exists); Assert.IsFalse(alphaFSFileInfo.EntryInfo.IsDirectory); Assert.IsFalse(alphaFSFileInfo.EntryInfo.IsMountPoint); Assert.IsTrue(alphaFSFileInfo.EntryInfo.IsReparsePoint); Assert.IsTrue(alphaFSFileInfo.EntryInfo.IsSymbolicLink); Assert.AreEqual(alphaFSFileInfo.EntryInfo.ReparsePointTag, Alphaleonis.Win32.Filesystem.ReparsePointTag.SymLink); } Console.WriteLine(); }
public override ItemList ProcessShow(ShowItem si, bool forceRefresh) { // for each tv show, optionally write a tvshow.nfo file if (TVSettings.Instance.NFOShows) { ItemList theActionList = new ItemList(); FileInfo tvshownfo = FileHelper.FileInFolder(si.AutoAddFolderBase, "tvshow.nfo"); SeriesInfo seriesInfo = si.TheSeries(); bool needUpdate = !tvshownfo.Exists || seriesInfo is null || seriesInfo.SrvLastUpdated > TimeZoneHelper.Epoch(tvshownfo.LastWriteTime); bool alreadyOnTheList = DoneNfo.Contains(tvshownfo.FullName); if ((forceRefresh || needUpdate) && !alreadyOnTheList) { theActionList.Add(new ActionNfo(tvshownfo, si)); DoneNfo.Add(tvshownfo.FullName); } return(theActionList); } return(base.ProcessShow(si, forceRefresh)); }
public override ItemList ProcessEpisode(ProcessedEpisode dbep, FileInfo filo, bool forceRefresh) { if (TVSettings.Instance.EpJPGs) { ItemList TheActionList = new ItemList(); string ban = dbep.GetFilename(); if (!string.IsNullOrEmpty(ban)) { string basefn = filo.Name; basefn = basefn.Substring(0, basefn.Length - filo.Extension.Length); //remove extension FileInfo imgjpg = FileHelper.FileInFolder(filo.Directory, basefn + ".jpg"); if (forceRefresh || !imgjpg.Exists) { TheActionList.Add(new ActionDownload(dbep.SI, dbep, imgjpg, ban, TVSettings.Instance.ShrinkLargeMede8erImages)); } } return(TheActionList); } return(base.ProcessEpisode(dbep, filo, forceRefresh)); }
public override ItemList ProcessEpisode(ProcessedEpisode dbep, FileInfo filo, bool forceRefresh) { if (TVSettings.Instance.EpTBNs || TVSettings.Instance.KODIImages) { ItemList TheActionList = new ItemList(); string ban = dbep.GetFilename(); if (!string.IsNullOrEmpty(ban)) { string basefn = filo.Name; basefn = basefn.Substring(0, basefn.Length - filo.Extension.Length); //remove extension FileInfo imgtbn = FileHelper.FileInFolder(filo.Directory, basefn + ".tbn"); if (!imgtbn.Exists || forceRefresh) { if (!(this.doneTBN.Contains(imgtbn.FullName))) { TheActionList.Add(new ActionDownload(dbep.SI, dbep, imgtbn, ban)); doneTBN.Add(filo.FullName); } } } return(TheActionList); } return(base.ProcessEpisode(dbep, filo, forceRefresh)); }
public override ItemList ProcessEpisode(ProcessedEpisode dbep, FileInfo filo, bool forceRefresh) { if (TVSettings.Instance.NFOEpisodes) { ItemList TheActionList = new ItemList(); string fn = filo.Name; fn = fn.Substring(0, fn.Length - filo.Extension.Length); fn += ".nfo"; FileInfo nfo = FileHelper.FileInFolder(filo.Directory, fn); if (!nfo.Exists || (dbep.Srv_LastUpdated > TimeZone.Epoch(nfo.LastWriteTime)) || forceRefresh) { //If we do not already have plans to put the file into place if (!(DownloadKODIMetaData.doneNFO.Contains(nfo.FullName))) { TheActionList.Add(new ActionNFO(nfo, dbep)); doneNFO.Add(nfo.FullName); } } return(TheActionList); } return(base.ProcessEpisode(dbep, filo, forceRefresh)); }
private void bnOK_Click(object sender, System.EventArgs e) { // we added a 'none' item at the top of the list, so adjust for that int n = lbDB.SelectedIndex; if (n == -1) { n = 0; } DbFile = n == 0 ? null : availableFiles[n - 1]; n = lbSettings.SelectedIndex; if (n == -1) { n = 0; } SettingsFile = n == 0 ? null : settingsList[n]; DialogResult = DialogResult.OK; Close(); }
public override ItemList ProcessEpisode(ProcessedEpisode dbep, FileInfo filo, bool forceRefresh) { if (TVSettings.Instance.EpTBNs || TVSettings.Instance.KODIImages) { ItemList theActionList = new ItemList(); if (dbep.type == ProcessedEpisode.ProcessedEpisodeType.merged) { //We have a merged episode, so we'll also download the images for the episodes had they been separate. foreach (Episode sourceEp in dbep.sourceEpisodes) { string foldername = filo.DirectoryName; string filename = TVSettings.Instance.FilenameFriendly( TVSettings.Instance.NamingStyle.GetTargetEpisodeName(sourceEp, dbep.SI.ShowName, dbep.SI.GetTimeZone(), dbep.SI.DVDOrder)); ActionDownloadImage b = DoEpisode(dbep.SI, sourceEp, new FileInfo(foldername + "/" + filename), ".jpg", forceRefresh); if (b != null) { theActionList.Add(b); } } } else { ActionDownloadImage a = DoEpisode(dbep.SI, dbep, filo, ".tbn", forceRefresh); if (a != null) { theActionList.Add(a); } } return(theActionList); } return(base.ProcessEpisode(dbep, filo, forceRefresh)); }
// https://stackoverflow.com/a/937558 public static bool IsFileLocked(this FileInfo file) { FileStream stream = null; try { stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None); } catch (IOException) { //the file is unavailable because it is: //still being written to //or being processed by another thread //or does not exist (has already been processed) return(true); } finally { stream?.Close(); } //file is not locked return(false); }
public override ItemList ProcessSeason(ShowItem si, string folder, int snum, bool forceRefresh) { if (TVSettings.Instance.FolderJpg) { // season folders JPGs ItemList TheActionList = new ItemList(); FileInfo fi = FileHelper.FileInFolder(folder, defaultFileName); if (!doneFolderJPG.Contains(fi.FullName) && (!fi.Exists || forceRefresh)) // some folders may come up multiple times { string bannerPath = ""; if (TVSettings.Instance.SeasonSpecificFolderJPG()) { //We are getting a Series Level image bannerPath = si.TheSeries().GetSeasonBannerPath(snum); } else { //We are getting a Show Level image bannerPath = si.TheSeries().GetImage(TVSettings.Instance.ItemForFolderJpg()); } if (!string.IsNullOrEmpty(bannerPath)) { TheActionList.Add(new ActionDownload(si, null, fi, bannerPath, TVSettings.Instance.ShrinkLargeMede8erImages)); } doneFolderJPG.Add(fi.FullName); } return(TheActionList); } return(base.ProcessSeason(si, folder, snum, forceRefresh)); }
private static (bool identifysuccess, int seasF, int epF, int maxEp) IdentifyFile([NotNull] ItemMissing me, [NotNull] FileInfo dce) { int season = me.Episode.AppropriateSeasonNumber; int epnum = me.Episode.AppropriateEpNum; bool regularMatch = FinderHelper.FindSeasEp(dce, out int seasF, out int epF, out int maxEp, me.Episode.Show) && seasF == season && epF == epnum; if (regularMatch) { return(true, seasF, epF, maxEp); } if (me.Episode.Show.UseSequentialMatch) { bool sequentialMatch = TVDoc.MatchesSequentialNumber(dce.Name, me.Episode); if (sequentialMatch) { return(true, season, epnum, me.Episode.EpNum2); } } return(false, 0, 0, 0); }
public ItemList ForceUpdateEpisode(DownloadIdentifier.DownloadType dt, ProcessedEpisode dbep, FileInfo filo) { ItemList TheActionList = new ItemList(); foreach (DownloadIdentifier di in this.Identifiers) { if (dt == di.GetDownloadType()) { TheActionList.Add(di.ProcessEpisode(dbep, filo, true)); } } return(TheActionList); }
public ActionPyTivoMeta(FileInfo nfo, ProcessedEpisode pe) : base(nfo, null) { Episode = pe; }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { if (string.IsNullOrEmpty(TVSettings.Instance.SABAPIKey) || String.IsNullOrEmpty(TVSettings.Instance.SABHostPort)) { prog.Invoke(totPct); return; } // get list of files being downloaded by SABnzbd // Something like: // http://localhost:8080/sabnzbd/api?mode=queue&apikey=xxx&start=0&limit=8888&output=xml string theURL = "http://" + TVSettings.Instance.SABHostPort + "/sabnzbd/api?mode=queue&start=0&limit=8888&output=xml&apikey=" + TVSettings.Instance.SABAPIKey; WebClient wc = new WebClient(); byte[] r = null; try { r = wc.DownloadData(theURL); } catch (WebException) { logger.Warn("Failed to obtain SABnzbd, please recheck settings: " + theURL); } if (r == null) { prog.Invoke(totPct); return; } try { SAB.result res = SAB.result.Deserialize(r); if (res != null && res.status == "False") { logger.Error("Error processing data from SABnzbd (Queue Check): {0}", res.error); prog.Invoke(totPct); return; } } catch { // wasn't a result/error combo. this is good! } SAB.queue sq = null; try { sq = SAB.queue.Deserialize(r); } catch (Exception e) { logger.Error(e, "Error processing data from SABnzbd (Queue Check)"); prog.Invoke(totPct); return; } System.Diagnostics.Debug.Assert(sq != null); // shouldn't happen if (sq?.slots == null || sq.slots.Length == 0) // empty queue { return; } ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = this.ActionList.Count + 2; int n = 1; foreach (Item Action1 in this.ActionList) { if (this.ActionCancel) { return; } prog.Invoke(startpct + (totPct - startpct) * (++n) / (c)); if (!(Action1 is ItemMissing)) { continue; } ItemMissing Action = (ItemMissing)(Action1); string showname = Helpers.SimplifyName(Action.Episode.SI.ShowName); foreach (SAB.queueSlotsSlot te in sq.slots) { //foreach (queueSlotsSlot te in qs) { FileInfo file = new FileInfo(te.filename); //if (!TVSettings.Instance.UsefulExtension(file.Extension, false)) // not a usefile file extension // continue; if (!FileHelper.SimplifyAndCheckFilename(file.FullName, showname, true, false)) { continue; } if (!TVDoc.FindSeasEp(file, out int seasF, out int epF, out int maxEp, Action.Episode.SI) || (seasF != Action.Episode.AppropriateSeasonNumber) || (epF != Action.Episode.AppropriateEpNum)) { continue; } toRemove.Add(Action1); newList.Add(new ItemSABnzbd(te, Action.Episode, Action.TheFileNoExt)); break; } } } foreach (Item i in toRemove) { this.ActionList.Remove(i); } foreach (Item Action in newList) { this.ActionList.Add(Action); } prog.Invoke(totPct); }
public ActionNFO(FileInfo nfo, ShowItem si) : base(nfo, si) { this.Episode = null; }
private bool?ReviewFile(bool unattended, [NotNull] FileInfo newFile, [NotNull] IReadOnlyCollection <ShowConfiguration> matchingShows, [NotNull] FileInfo existingFile, [NotNull] ProcessedEpisode pep, IDialogParent owner) { FileHelper.VideoComparison result = FileHelper.BetterQualityFile(existingFile, newFile); FileHelper.VideoComparison newResult = result; if (TVSettings.Instance.ReplaceWithBetterQuality && TVSettings.Instance.ForceSystemToDecideOnUpgradedFiles && IsNotClearCut(result)) { //User has asked us to make a call newResult = existingFile.Length >= newFile.Length ? FileHelper.VideoComparison.firstFileBetter : FileHelper.VideoComparison.secondFileBetter; } switch (newResult) { case FileHelper.VideoComparison.secondFileBetter: if (TVSettings.Instance.ReplaceWithBetterQuality) { if (matchingShows.Count > 1) { LOGGER.Warn( $"Keeping {newFile.FullName}. Although it is better quality than {existingFile.FullName}, there are other shows ({matchingShows.Select(item => item.ShowName).ToCsv()}) that match."); } else { UpgradeFile(newFile, pep, existingFile); } } else { LOGGER.Warn( $"Keeping {newFile.FullName} as it is better quality than some of the current files for that show (Auto Replace with better quality files is turned off)"); } return(false); case FileHelper.VideoComparison.cantTell: case FileHelper.VideoComparison.similar: if (unattended) { LOGGER.Info( $"Keeping {newFile.FullName} as it might be better quality than {existingFile.FullName}"); return(false); } else { if (matchingShows.Count <= 1) { return(AskUserAboutFileReplacement(newFile, existingFile, pep, owner)); } LOGGER.Warn( $"Keeping {newFile.FullName}. Although it is better quality than {existingFile.FullName}, there are other shows ({matchingShows.Select(item => item.ShowName).ToCsv()}) that match."); return(false); } //the other cases of the files being the same or the existing file being better are not enough to save the file case FileHelper.VideoComparison.firstFileBetter: break; case FileHelper.VideoComparison.same: break; default: throw new ArgumentOutOfRangeException(); } return(null); }
public override ItemList ProcessSeason(ShowItem si, string folder, int snum, bool forceRefresh) { if (TVSettings.Instance.KODIImages) { ItemList TheActionList = new ItemList(); if (TVSettings.Instance.DownloadFrodoImages()) { //If we have KODI New style images being downloaded then we want to check that 3 files exist //for the series: //http://wiki.xbmc.org/index.php?title=XBMC_v12_(Frodo)_FAQ#Local_images //poster //banner //fanart - we do not have the option in TVDB to get season specific fanart, so we'll leave that string filenamePrefix = ""; if (!si.AutoAdd_FolderPerSeason) { // We have multiple seasons in the same folder // We need to do slightly more work to come up with the filenamePrefix filenamePrefix = "season"; if (snum == 0) { filenamePrefix += "-specials"; } else if (snum < 10) { filenamePrefix += "0" + snum; } else { filenamePrefix += snum; } filenamePrefix += "-"; } FileInfo posterJPG = FileHelper.FileInFolder(folder, filenamePrefix + "poster.jpg"); if (forceRefresh || !posterJPG.Exists) { string path = si.TheSeries().GetSeasonBannerPath(snum); if (!string.IsNullOrEmpty(path)) { TheActionList.Add(new ActionDownload(si, null, posterJPG, path)); } } FileInfo bannerJPG = FileHelper.FileInFolder(folder, filenamePrefix + "banner.jpg"); if (forceRefresh || !bannerJPG.Exists) { string path = si.TheSeries().GetSeasonWideBannerPath(snum); if (!string.IsNullOrEmpty(path)) { TheActionList.Add(new ActionDownload(si, null, bannerJPG, path)); } } } if (TVSettings.Instance.DownloadEdenImages()) { string filenamePrefix = "season"; if (snum == 0) { filenamePrefix += "-specials"; } else if (snum < 10) { filenamePrefix += "0" + snum; } else { filenamePrefix += snum; } FileInfo posterTBN = FileHelper.FileInFolder(si.AutoAdd_FolderBase, filenamePrefix + ".tbn"); if (forceRefresh || !posterTBN.Exists) { string path = si.TheSeries().GetSeasonBannerPath(snum); if (!string.IsNullOrEmpty(path)) { TheActionList.Add(new ActionDownload(si, null, posterTBN, path)); } } } return(TheActionList); } return(base.ProcessSeason(si, folder, snum, forceRefresh)); }
private void CompareFileInfos(System.IO.FileInfo expected, Alphaleonis.Win32.Filesystem.FileInfo actual, bool exists) { if (expected == null || actual == null) { Assert.AreEqual(expected, actual, "The two FileInfo instances are not the same, but are expected to be."); } UnitTestConstants.Dump(expected); Console.WriteLine(); UnitTestConstants.Dump(actual); if (exists) { Assert.IsTrue(expected.Exists && actual.Exists, "The file does not exist, but is expected to."); } else { Assert.IsFalse(expected.Exists && actual.Exists, "The file exists, but is expected not to."); } var cnt = -1; while (cnt != 15) { cnt++; // Compare values of both instances. switch (cnt) { case 0: Assert.AreEqual(expected.Attributes, actual.Attributes, "The property Attributes is not the same, but is expected to."); break; case 1: Assert.AreEqual(expected.CreationTime, actual.CreationTime, "The property CreationTime is not the same, but is expected to."); break; case 2: Assert.AreEqual(expected.CreationTimeUtc, actual.CreationTimeUtc, "The property CreationTimeUtc is not the same, but is expected to."); break; // Need .ToString() here since the object types are obviously not the same. case 3: Assert.AreEqual(expected.Directory.ToString(), actual.Directory.ToString(), "The property Directory is not the same, but is expected to."); break; case 4: Assert.AreEqual(expected.DirectoryName, actual.DirectoryName, "The property DirectoryName is not the same, but is expected to."); break; case 5: Assert.AreEqual(expected.Exists, actual.Exists, "The property Exists is not the same, but is expected to."); break; case 6: Assert.AreEqual(expected.Extension, actual.Extension, "The property Extension is not the same, but is expected to."); break; case 7: Assert.AreEqual(expected.FullName, actual.FullName, "The property FullName is not the same, but is expected to."); break; case 8: Assert.AreEqual(expected.IsReadOnly, actual.IsReadOnly, "The property IsReadOnly is not the same, but is expected to."); break; case 9: Assert.AreEqual(expected.LastAccessTime, actual.LastAccessTime, "The property LastAccessTime is not the same, but is expected to."); break; case 10: Assert.AreEqual(expected.LastAccessTimeUtc, actual.LastAccessTimeUtc, "The property LastAccessTimeUtc is not the same, but is expected to."); break; case 11: Assert.AreEqual(expected.LastWriteTime, actual.LastWriteTime, "The property LastWriteTime is not the same, but is expected to."); break; case 12: Assert.AreEqual(expected.LastWriteTimeUtc, actual.LastWriteTimeUtc, "The property LastWriteTimeUtc is not the same, but is expected to."); break; case 13: if (exists) { Assert.AreEqual(expected.Length, actual.Length, "The property Length is not the same, but is expected to."); } break; case 14: Assert.AreEqual(expected.Name, actual.Name, "The property Name is not the same, but is expected to."); break; } } }
private List<EddbDataDTO> GetSystemsFromApi(bool resetLocalCache) { var systems = new List<EddbDataDTO>(); var localFile = new FileInfo(Path.Combine(Environment.CurrentDirectory, _eddbLocalCacheFileName)); if (!resetLocalCache && localFile.Exists) { using (StreamReader r = new StreamReader(localFile.FullName)) { string json = r.ReadToEnd(); systems = JsonConvert.DeserializeObject<List<EddbDataDTO>>(json); } } else { using (WebClient wc = new WebClient()) { var json = wc.DownloadString(_eddbSystemApiAddress.AbsoluteUri); systems = JsonConvert.DeserializeObject<List<EddbDataDTO>>(json); // save to local file. if (localFile.Exists) { localFile.Delete(true); } using ( StreamWriter outputFile = new StreamWriter(Path.Combine(Environment.CurrentDirectory.ToString(), _eddbLocalCacheFileName))) { outputFile.WriteLine(JsonConvert.SerializeObject(systems)); } } } return systems; }
private void ReviewFileInDownloadDirectory(bool unattended, FileInfo fi, [NotNull] List <ShowConfiguration> matchingShows, IDialogParent owner) { bool fileCanBeDeleted = TVSettings.Instance.RemoveDownloadDirectoriesFiles; ProcessedEpisode firstMatchingPep = null; foreach (ShowConfiguration si in matchingShows) { FinderHelper.FindSeasEp(fi, out int seasF, out int epF, out int _, si, out TVSettings.FilenameProcessorRE re); if (!si.SeasonEpisodes.ContainsKey(seasF)) { LOGGER.Info($"Can't find the right season for {fi.FullName} coming out as S{seasF}E{epF} using rule '{re?.Notes}'"); fileCanBeDeleted = false; continue; } ProcessedEpisode?pep = si.SeasonEpisodes[seasF].FirstOrDefault(ep => ep.AppropriateEpNum == epF); if (pep == null) { LOGGER.Info($"Can't find the right episode for {fi.FullName} coming out as S{seasF}E{epF} using rule '{re?.Notes}'"); fileCanBeDeleted = false; continue; } firstMatchingPep = pep; List <FileInfo> encumbants = dfc.FindEpOnDisk(pep, false); if (encumbants.Count == 0) { //File is needed as there are no files for that cachedSeries/episode fileCanBeDeleted = false; CopyFutureDatedFile(fi, pep, MDoc); } else { foreach (FileInfo existingFile in encumbants) { if (existingFile.FullName.Equals(fi.FullName, StringComparison.InvariantCultureIgnoreCase)) { //the user has put the search folder and the download folder in the same place - DO NOT DELETE fileCanBeDeleted = false; continue; } bool?deleteFile = ReviewFile(unattended, fi, matchingShows, existingFile, pep, owner); if (deleteFile.HasValue && deleteFile.Value == false) { fileCanBeDeleted = false; } } } } if (fileCanBeDeleted) { LOGGER.Info( $"Removing {fi.FullName} as it matches { matchingShows.Select(s => s.ShowName).ToCsv()} and no episodes are needed"); returnActions.Add(new ActionDeleteFile(fi, firstMatchingPep, TVSettings.Instance.Tidyup)); } else { filesThatMayBeNeeded.Add(fi); } }
// ReSharper disable once FunctionComplexityOverflow protected bool ReviewFile(ItemMissing me, ItemList addTo, FileInfo dce, TVDoc.ScanSettings settings, bool addMergeRules, bool preventMove, bool doExtraFiles, bool useFullPath) { if (settings.Token.IsCancellationRequested) { return(false); } bool matched = false; try { if (dce.IgnoreFile()) { return(false); } //do any of the possible names for the series match the filename? matched = me.Episode.Show.NameMatch(dce, useFullPath); if (!matched) { return(false); } (bool identifySuccess, int seasF, int epF, int maxEp) = IdentifyFile(me, dce); if (!identifySuccess) { return(false); } if (maxEp != -1 && addMergeRules) { me = UpdateMissingItem(me, dce, epF, maxEp, seasF); } FileInfo fi = new FileInfo(me.TheFileNoExt + dce.Extension); if (preventMove) { //We do not want to move the file, just rename it fi = new FileInfo(dce.DirectoryName + Path.DirectorySeparatorChar + me.Filename + dce.Extension); } if (dce.FullName != fi.FullName && !FindExistingActionFor(addTo, dce)) { // don't remove the base search folders bool doTidyup = !TVSettings.Instance.DownloadFolders.Any(folder => folder.SameDirectoryLocation(fi.Directory.FullName)); addTo.Add(new ActionCopyMoveRename(ActionCopyMoveRename.Op.copy, dce, fi, me.Episode, doTidyup, me, MDoc)); } if (doExtraFiles) { DownloadIdentifiersController di = new DownloadIdentifiersController(); // if we're copying/moving a file across, we might also want to make a thumbnail or NFO for it addTo.Add(di.ProcessEpisode(me.Episode, fi)); } return(true); } catch (PathTooLongException e) { WarnPathTooLong(me, dce, e, matched); } return(false); }
public ActionNFO(FileInfo nfo, ProcessedEpisode pe) : base(nfo, null) { this.Episode = pe; }
public static void SaveCache(ConcurrentDictionary <int, CachedSeriesInfo> series, ConcurrentDictionary <int, CachedMovieInfo> movies, [NotNull] FileInfo cacheFile, long timestamp) { DirectoryInfo di = cacheFile.Directory; if (!di.Exists) { di.Create(); } Logger.Info("Saving Cache to: {0}", cacheFile.FullName); try { RotateCacheFiles(cacheFile); // write ourselves to disc for next time. use same structure as thetvdb.com (limited fields, though) // to make loading easy XmlWriterSettings settings = new XmlWriterSettings { Indent = true, NewLineOnAttributes = true }; using (XmlWriter writer = XmlWriter.Create(cacheFile.FullName, settings)) { writer.WriteStartDocument(); writer.WriteStartElement("Data"); writer.WriteAttributeToXml("time", timestamp); foreach (KeyValuePair <int, CachedSeriesInfo> kvp in series) { if (kvp.Value.SrvLastUpdated != 0) { kvp.Value.WriteXml(writer); foreach (Episode e in kvp.Value.Episodes) { e.WriteXml(writer); } } else { Logger.Info($"Cannot save {kvp.Value.TvdbCode} ({kvp.Value.Name}) as it has not been updated at all."); } } // // <BannersCache> // <BannersItem> // <SeriesId>123</SeriesId> // <Banners> // <Banner> writer.WriteStartElement("BannersCache"); foreach (KeyValuePair <int, CachedSeriesInfo> kvp in series) { writer.WriteStartElement("BannersItem"); writer.WriteElement("SeriesId", kvp.Key); writer.WriteStartElement("Banners"); //We need to write out all banners that we have in any of the collections. foreach (Banner ban in kvp.Value.AllBanners.Select(kvp3 => kvp3.Value)) { ban.WriteXml(writer); } writer.WriteEndElement(); //Banners writer.WriteEndElement(); //BannersItem } writer.WriteEndElement(); // BannersCache foreach (KeyValuePair <int, CachedMovieInfo> kvp in movies) { if (!kvp.Value.IsSearchResultOnly) { kvp.Value.WriteXml(writer); } else { Logger.Info($"Cannot save {kvp.Value.TvdbCode} ({kvp.Value.Name}) as it is a search result that has not been used."); } } // TODO SAVE MIE BANNERS if we ever have them // <BannersCache> // <BannersItem> // <SeriesId>123</SeriesId> // <Banners> // <Banner> /*writer.WriteStartElement("BannersCache"); * * foreach (KeyValuePair<int, CachedSeriesInfo> kvp in series) * { * writer.WriteStartElement("BannersItem"); * * writer.WriteElement("SeriesId", kvp.Key); * * writer.WriteStartElement("Banners"); * * //We need to write out all banners that we have in any of the collections. * * foreach (Banner ban in kvp.Value.AllBanners.Select(kvp3 => kvp3.Value)) * { * ban.WriteXml(writer); * } * * writer.WriteEndElement(); //Banners * writer.WriteEndElement(); //BannersItem * } * * writer.WriteEndElement(); // BannersCache*/ writer.WriteEndElement(); // data writer.WriteEndDocument(); } } catch (Exception e) { Logger.Error(e, $"Failed to save Cache to {cacheFile.FullName}"); } }
private void AlphaFS_Directory_EnumerateAlternateDataStreams(bool isNetwork) { using (var tempRoot = new TemporaryDirectory(isNetwork)) { var folder = tempRoot.RandomDirectoryFullPath; Console.WriteLine("Input Directory Path: [{0}]", folder); var myStream = "ӍƔŞtrëƛɱ-" + tempRoot.RandomString; var myStream2 = "myStreamTWO-" + tempRoot.RandomString; var allStreams = new[] { myStream, myStream2 }; var streamStringContent = "(1) Computer: [" + Environment.MachineName + "]" + "\tHello there, " + Environment.UserName; Console.WriteLine("\nA directory is created and {0} streams are added.", allStreams.Length.ToString(CultureInfo.CurrentCulture)); var di = new Alphaleonis.Win32.Filesystem.DirectoryInfo(folder); di.Create(); const int defaultStreamsDirectory = 0; // The default number of data streams for a folder. var currentNumberofStreams = di.EnumerateAlternateDataStreams().Count(); Assert.AreEqual(defaultStreamsDirectory, currentNumberofStreams, "Total amount of default streams do not match."); Assert.AreEqual(currentNumberofStreams, Alphaleonis.Win32.Filesystem.Directory.EnumerateAlternateDataStreams(folder).Count(), "Total amount of Directory.EnumerateAlternateDataStreams() streams do not match."); // Create alternate data streams. // Because of the colon, you must supply a full path and use PathFormat.FullPath or PathFormat.LongFullPath, // to prevent a: "NotSupportedException: path is in an invalid format." exception. var stream1Name = folder + Alphaleonis.Win32.Filesystem.Path.StreamSeparator + myStream; var stream2Name = folder + Alphaleonis.Win32.Filesystem.Path.StreamSeparator + myStream2; Alphaleonis.Win32.Filesystem.File.WriteAllLines(stream1Name, UnitTestConstants.StreamArrayContent, Alphaleonis.Win32.Filesystem.PathFormat.FullPath); Alphaleonis.Win32.Filesystem.File.WriteAllText(stream2Name, streamStringContent, Alphaleonis.Win32.Filesystem.PathFormat.FullPath); var newNumberofStreams = Alphaleonis.Win32.Filesystem.Directory.EnumerateAlternateDataStreams(folder).Count(); Console.WriteLine("\n\nNew stream count: [{0}]", newNumberofStreams); // Enumerate all streams from the folder. foreach (var stream in di.EnumerateAlternateDataStreams()) { Assert.IsTrue(UnitTestConstants.Dump(stream, -10)); } // Show the contents of our streams. Console.WriteLine(); foreach (var streamName in allStreams) { Console.WriteLine("\n\tStream name: [{0}]", streamName); // Because of the colon, you must supply a full path and use PathFormat.FullPath or PathFormat.LongFullPath, // to prevent a: "NotSupportedException: path is in an invalid format." exception. foreach (var line in Alphaleonis.Win32.Filesystem.File.ReadAllLines(folder + Alphaleonis.Win32.Filesystem.Path.StreamSeparator + streamName, Alphaleonis.Win32.Filesystem.PathFormat.FullPath)) { Console.WriteLine("\t\t{0}", line); } } // Show DirectoryInfo instance data of the streams. var dirInfo = new Alphaleonis.Win32.Filesystem.DirectoryInfo(stream1Name, Alphaleonis.Win32.Filesystem.PathFormat.LongFullPath); Console.WriteLine(); UnitTestConstants.Dump(dirInfo, -17); // Show FileInfo instance data of the streams. var fileInfo1 = new Alphaleonis.Win32.Filesystem.FileInfo(stream1Name, Alphaleonis.Win32.Filesystem.PathFormat.LongFullPath); var fileInfo2 = new Alphaleonis.Win32.Filesystem.FileInfo(stream2Name, Alphaleonis.Win32.Filesystem.PathFormat.LongFullPath); Console.WriteLine(); UnitTestConstants.Dump(fileInfo1, -17); UnitTestConstants.Dump(fileInfo2, -17); Assert.AreEqual(myStream, fileInfo1.Name); Assert.AreEqual(myStream2, fileInfo2.Name); Assert.IsNull(fileInfo1.EntryInfo); Assert.IsNull(fileInfo2.EntryInfo); } Console.WriteLine(); }
Task CreateTempAppHostConfigAsync(Path websitePath, Path templateConfigFilePath, int httpPort, int httpsPort, Path tempFilePath, Path iisExpressPath, string customHostName = "", int customHostNameHttpsPort = -1) { var fileInfo = new FileInfo(tempFilePath.FullName); if (!Directory.Exists(fileInfo.Directory.FullName)) { Directory.CreateDirectory(fileInfo.Directory.FullName); } File.Copy(templateConfigFilePath.FullName, tempFilePath.FullName, overwrite: true); if (!websitePath.Exists) { throw new InvalidOperationException("The web site path is null or empty"); } AddSiteToTempApphostConfig(httpPort, httpsPort, tempFilePath, websitePath, iisExpressPath, customHostName, customHostNameHttpsPort); return Task.FromResult(0); }
public static async Task <VirtualFile> Analyze(Context context, VirtualFile parent, string abs_path, string rel_path, bool topLevel) { var hash = abs_path.FileHash(); var fi = new FileInfo(abs_path); if (!context.UseExtendedHashes && FileExtractor.MightBeArchive(abs_path)) { var result = await TryGetContentsFromServer(hash); if (result != null) { Utils.Log($"Downloaded VFS data for {Path.GetFileName(abs_path)}"); VirtualFile Convert(IndexedVirtualFile file, string path, VirtualFile vparent) { var vself = new VirtualFile { Context = context, Name = path, Parent = vparent, Size = file.Size, LastModified = fi.LastWriteTimeUtc.Ticks, LastAnalyzed = DateTime.Now.Ticks, Hash = file.Hash, }; vself.Children = file.Children.Select(f => Convert(f, f.Name, vself)).ToImmutableList(); return(vself); } return(Convert(result, rel_path, parent)); } } var self = new VirtualFile { Context = context, Name = rel_path, Parent = parent, Size = fi.Length, LastModified = fi.LastWriteTimeUtc.Ticks, LastAnalyzed = DateTime.Now.Ticks, Hash = hash }; if (context.UseExtendedHashes) { self.ExtendedHashes = ExtendedHashes.FromFile(abs_path); } if (FileExtractor.CanExtract(abs_path)) { using (var tempFolder = context.GetTemporaryFolder()) { await FileExtractor.ExtractAll(context.Queue, abs_path, tempFolder.FullName); var list = await Directory.EnumerateFiles(tempFolder.FullName, "*", SearchOption.AllDirectories) .PMap(context.Queue, abs_src => Analyze(context, self, abs_src, abs_src.RelativeTo(tempFolder.FullName), false)); self.Children = list.ToImmutableList(); } } return(self); }
private void DumpRefresh(bool isLocal) { #region Setup Console.WriteLine("\n=== TEST {0} ===", isLocal ? Local : Network); string tempPathSysIo = Path.GetTempPath("FileInfo.Refresh()-file-SysIo-" + Path.GetRandomFileName()); string tempPath = Path.GetTempPath("FileInfo.Refresh()-file-AlphaFS-" + Path.GetRandomFileName()); if (!isLocal) tempPathSysIo = Path.LocalToUnc(tempPathSysIo); if (!isLocal) tempPath = Path.LocalToUnc(tempPath); Console.WriteLine("\nInput File Path: [{0}]", tempPath); #endregion // Setup #region Refresh try { System.IO.FileInfo fiSysIo = new System.IO.FileInfo(tempPathSysIo); FileInfo fi = new FileInfo(tempPath); bool existsSysIo = fiSysIo.Exists; bool exists = fi.Exists; Console.WriteLine("\nnew FileInfo(): Exists (Should be {0}): [{1}]", existsSysIo, exists); // false Assert.AreEqual(existsSysIo, exists); FileStream fsSysIo = fiSysIo.Create(); FileStream fs = fi.Create(); existsSysIo = fiSysIo.Exists; exists = fi.Exists; Console.WriteLine("\nfi.Create(): Exists (Should be {0}): [{1}]", existsSysIo, exists); // false Assert.AreEqual(existsSysIo, exists); fiSysIo.Refresh(); fi.Refresh(); existsSysIo = fiSysIo.Exists; exists = fi.Exists; Console.WriteLine("\nfi.Refresh(): Exists (Should be {0}): [{1}]", existsSysIo, exists); // true Assert.AreEqual(existsSysIo, exists); fsSysIo.Close(); fs.Close(); existsSysIo = fiSysIo.Exists; exists = fi.Exists; Console.WriteLine("\nfi.Close(): Exists (Should be {0}): [{1}]", existsSysIo, exists); // true Assert.AreEqual(existsSysIo, exists); fiSysIo.Delete(); fi.Delete(); existsSysIo = fiSysIo.Exists; exists = fi.Exists; Console.WriteLine("\nfi.Delete(): Exists (Should be {0}): [{1}]", existsSysIo, exists); // true Assert.AreEqual(existsSysIo, exists); fiSysIo.Refresh(); fi.Refresh(); existsSysIo = fiSysIo.Exists; exists = fi.Exists; Console.WriteLine("\nfi.Refresh(): Exists (Should be False): [{0}]", exists); // false Assert.AreEqual(existsSysIo, exists); } finally { File.Delete(tempPath); Assert.IsFalse(File.Exists(tempPath), "Cleanup failed: File should have been removed."); File.Delete(tempPathSysIo); Assert.IsFalse(File.Exists(tempPath), "Cleanup failed: File should have been removed."); Console.WriteLine(); } #endregion // Refresh }
private bool ReviewFile(ItemMissing me, ItemList addTo, DirCacheEntry dce) { if (ActionCancel) { return(true); } int season = me.Episode.AppropriateSeasonNumber; int epnum = me.Episode.AppropriateEpNum; bool matched = false; try { if (FileHelper.IgnoreFile(dce.TheFile)) { return(false); } //do any of the possible names for the series match the filename? matched = (me.Episode.Show.GetSimplifiedPossibleShowNames() .Any(name => FileHelper.SimplifyAndCheckFilename(dce.SimplifiedFullName, name))); if (matched) { bool regularMatch = TVDoc.FindSeasEp(dce.TheFile, out int seasF, out int epF, out int maxEp, me.Episode.Show) && seasF == season && epF == epnum; bool sequentialMatch = me.Episode.Show.UseSequentialMatch && TVDoc.MatchesSequentialNumber(dce.TheFile.Name, ref seasF, ref epF, me.Episode) && seasF == season && epF == epnum; if (regularMatch || sequentialMatch) { if (maxEp != -1 && TVSettings.Instance.AutoMergeDownloadEpisodes) { ShowRule sr = new ShowRule { DoWhatNow = RuleAction.kMerge, First = epF, Second = maxEp }; me.Episode.Show?.AddSeasonRule(seasF, sr); LOGGER.Info( $"Looking at {me.Episode.Show.ShowName} and have identified that episode {epF} and {maxEp} of season {seasF} have been merged into one file {dce.TheFile.FullName}"); LOGGER.Info($"Added new rule automatically for {sr}"); //Regenerate the episodes with the new rule added ShowLibrary.GenerateEpisodeDict(me.Episode.Show); //Get the newly created processed episode we are after // ReSharper disable once InconsistentNaming ProcessedEpisode newPE = me.Episode; foreach (ProcessedEpisode pe in me.Episode.Show.SeasonEpisodes[seasF]) { if (pe.AppropriateEpNum == epF && pe.EpNum2 == maxEp) { newPE = pe; } } me = new ItemMissing(newPE, me.TargetFolder, TVSettings.Instance.FilenameFriendly(TVSettings.Instance.NamingStyle.NameFor(newPE))); } FileInfo fi = new FileInfo(me.TheFileNoExt + dce.TheFile.Extension); if (TVSettings.Instance.PreventMove) { //We do not want to move the file, just rename it fi = new FileInfo(dce.TheFile.DirectoryName + System.IO.Path.DirectorySeparatorChar + me.Filename + dce.TheFile.Extension); } // don't remove the base search folders bool doTidyup = true; foreach (string folder in TVSettings.Instance.DownloadFolders) { if (folder.SameDirectoryLocation(fi.Directory.FullName)) { doTidyup = false; break; } } if (dce.TheFile.FullName != fi.FullName) { addTo.Add(new ActionCopyMoveRename(ActionCopyMoveRename.Op.copy, dce.TheFile, fi, me.Episode, doTidyup ? TVSettings.Instance.Tidyup : null, me)); } DownloadIdentifiersController di = new DownloadIdentifiersController(); // if we're copying/moving a file across, we might also want to make a thumbnail or NFO for it addTo.Add(di.ProcessEpisode(me.Episode, fi)); return(true); } } } catch (System.IO.PathTooLongException e) { string t = "Path too long. " + dce.TheFile.FullName + ", " + e.Message; LOGGER.Warn(e, "Path too long. " + dce.TheFile.FullName); t += ". More information is available in the log file"; if ((!Doc.Args.Unattended) && (!Doc.Args.Hide)) { MessageBox.Show(t, "Path too long", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } t = "DirectoryName " + dce.TheFile.DirectoryName + ", File name: " + dce.TheFile.Name; t += matched ? ", matched. " : ", no match. "; if (matched) { t += "Show: " + me.Episode.TheSeries.Name + ", Season " + season + ", Ep " + epnum + ". "; t += "To: " + me.TheFileNoExt; } LOGGER.Warn(t); } return(false); }
private void AlphaFS_EnumerateAlternateDataStreams(bool isNetwork) { using (var tempRoot = new TemporaryDirectory(isNetwork)) { var file = tempRoot.RandomTxtFileFullPath; Console.WriteLine("Input File Path: [{0}]", file); var myStream = "ӍƔŞtrëƛɱ-" + tempRoot.RandomString; var myStream2 = "myStreamTWO-" + tempRoot.RandomString; var allStreams = new[] { myStream, myStream2 }; var streamStringContent = "(1) Computer: [" + Environment.MachineName + "]" + "\tHello there, " + Environment.UserName; var tenNumbers = "0123456789"; Console.WriteLine("\nA file is created and {0} streams are added.", allStreams.Length.ToString(CultureInfo.CurrentCulture)); // Create file and add 10 characters to it, file is created in ANSI format. System.IO.File.WriteAllText(file, tenNumbers); var fi = new Alphaleonis.Win32.Filesystem.FileInfo(file); const int defaultStreamsFile = 1; // The default number of data streams for a file. var currentNumberofStreams = fi.EnumerateAlternateDataStreams().Count(); Assert.AreEqual(defaultStreamsFile, currentNumberofStreams, "Total amount of default streams do not match."); Assert.AreEqual(currentNumberofStreams, Alphaleonis.Win32.Filesystem.File.EnumerateAlternateDataStreams(file).Count(), "Total amount of File.EnumerateAlternateDataStreams() streams do not match."); var fileSize = Alphaleonis.Win32.Filesystem.File.GetSize(file); Assert.AreEqual(tenNumbers.Length, fileSize); // Create alternate data streams. // Because of the colon, you must supply a full path and use PathFormat.FullPath or PathFormat.LongFullPath, // to prevent a: "NotSupportedException: path is in an invalid format." exception. var stream1Name = file + Alphaleonis.Win32.Filesystem.Path.StreamSeparator + myStream; var stream2Name = file + Alphaleonis.Win32.Filesystem.Path.StreamSeparator + myStream2; Alphaleonis.Win32.Filesystem.File.WriteAllLines(stream1Name, UnitTestConstants.StreamArrayContent, Alphaleonis.Win32.Filesystem.PathFormat.FullPath); Alphaleonis.Win32.Filesystem.File.WriteAllText(stream2Name, streamStringContent, Alphaleonis.Win32.Filesystem.PathFormat.FullPath); var newNumberofStreams = Alphaleonis.Win32.Filesystem.File.EnumerateAlternateDataStreams(file).Count(); Console.WriteLine("\n\nNew stream count: [{0}]", newNumberofStreams); // Enumerate all streams from the file. foreach (var stream in fi.EnumerateAlternateDataStreams()) { Assert.IsTrue(UnitTestConstants.Dump(stream, -10)); // The default stream, a file as we know it. if (Alphaleonis.Utils.IsNullOrWhiteSpace(stream.StreamName)) { Assert.AreEqual(fileSize, stream.Size); } } // Show the contents of our streams. Console.WriteLine(); foreach (var streamName in allStreams) { Console.WriteLine("\n\tStream name: [{0}]", streamName); // Because of the colon, you must supply a full path and use PathFormat.FullPath or PathFormat.LongFullPath, // to prevent a: "NotSupportedException: path is in an invalid format." exception. foreach (var line in Alphaleonis.Win32.Filesystem.File.ReadAllLines(file + Alphaleonis.Win32.Filesystem.Path.StreamSeparator + streamName, Alphaleonis.Win32.Filesystem.PathFormat.FullPath)) { Console.WriteLine("\t\t{0}", line); } } // Show FileInfo instance data of the streams. var fileInfo1 = new Alphaleonis.Win32.Filesystem.FileInfo(stream1Name, Alphaleonis.Win32.Filesystem.PathFormat.LongFullPath); var fileInfo2 = new Alphaleonis.Win32.Filesystem.FileInfo(stream2Name, Alphaleonis.Win32.Filesystem.PathFormat.LongFullPath); Console.WriteLine(); UnitTestConstants.Dump(fileInfo1, -17); UnitTestConstants.Dump(fileInfo2, -17); Assert.AreEqual(myStream, fileInfo1.Name); Assert.AreEqual(myStream2, fileInfo2.Name); Assert.IsNull(fileInfo1.EntryInfo); Assert.IsNull(fileInfo2.EntryInfo); } Console.WriteLine(); }
private static string GetFileSize([NotNull] FileInfo file) { return(file.Length.Bytes().Humanize("#.#")); }
public void StartTorrentDownload(FileInfo torrentFile) { string torrentFileName = torrentFile.Name; System.Diagnostics.Process.Start(TVSettings.Instance.uTorrentPath, "/directory \"" + torrentFile.Directory.FullName + "\" \"" + torrentFileName + "\""); }