private static ShowItemMissing UpdateMissingItem([NotNull] ShowItemMissing me, [NotNull] FileInfo dce, int epF, int maxEp, int seasF) { ShowRule sr = new ShowRule { DoWhatNow = RuleAction.kMerge, First = epF, Second = maxEp }; me.MissingEpisode.Show.AddSeasonRule(seasF, sr); LOGGER.Info( $"Looking at {me.MissingEpisode.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.MissingEpisode.Show); //Get the newly created processed episode we are after // ReSharper disable once InconsistentNaming ProcessedEpisode newPE = me.MissingEpisode; foreach (ProcessedEpisode pe in me.MissingEpisode.Show.SeasonEpisodes[seasF]) { if (pe.AppropriateEpNum == epF && pe.EpNum2 == maxEp) { newPE = pe; } } return(new ShowItemMissing(newPE, me.TargetFolder)); }
public EditSeason([NotNull] ShowItem si, int seasonNumber, CustomEpisodeName style) { mOriginalEps = ShowLibrary.GenerateEpisodes(si, seasonNumber, false); nameStyle = style; InitializeComponent(); episodesToAddToSeen = new List <ProcessedEpisode>(); episodesToRemoveFromSeen = new List <ProcessedEpisode>(); show = si; mSeasonNumber = seasonNumber; workingRuleSet = si.SeasonRules.ContainsKey(seasonNumber) ? new List <ShowRule>(si.SeasonRules[seasonNumber]) : new List <ShowRule>(); txtShowName.Text = si.ShowName; txtSeasonNumber.Text = seasonNumber.ToString(); FillRuleList(false, 0); FillSeenEpisodes(false); lvSeenEpisodes.ListViewItemSorter = new NumberAsTextSorter(0); lvSeenEpisodes.Sort(); }
private static string GuessShowName([NotNull] FoundFolder ai, [NotNull] ShowLibrary library) { // see if we can guess a season number and show name, too // Assume is blah\blah\blah\show\season X string showName = ai.Folder.FullName; foreach (string seasonWord in library.SeasonWords()) { string seasonFinder = ".*" + seasonWord + "[ _\\.]+([0-9]+).*"; if (Regex.Matches(showName, seasonFinder, RegexOptions.IgnoreCase).Count == 0) { continue; } try { // remove season folder from end of the path showName = Regex.Replace(showName, "(.*)\\\\" + seasonFinder, "$1", RegexOptions.IgnoreCase); break; } catch (ArgumentException) { } } // assume last folder element is the show name showName = showName.Substring(showName.LastIndexOf(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) + 1); return(showName); }
public static void GuessShowItem([NotNull] PossibleNewTvShow ai, [NotNull] ShowLibrary library, bool showErrorMsgBox) { string languageCode = TVSettings.Instance.DefaultProvider == TVDoc.ProviderType.TMDB ? TVSettings.Instance.TMDBLanguage : TVSettings.Instance.PreferredLanguageCode; string showName = GuessShowName(ai, library); //todo - (BulkAdd Manager needs to work for new providers) int tvdbId = FindTVDBShowCode(ai); if (string.IsNullOrEmpty(showName) && tvdbId == -1) { return; } if (tvdbId != -1) { try { CachedSeriesInfo cachedSeries = TheTVDB.LocalCache.Instance.GetSeriesAndDownload(tvdbId, showErrorMsgBox); if (cachedSeries != null) { ai.SetId(tvdbId, TVDoc.ProviderType.TheTVDB); return; } } catch (MediaNotFoundException) { //continue to try the next method } } CachedSeriesInfo ser = TheTVDB.LocalCache.Instance.GetSeries(showName, showErrorMsgBox, languageCode); if (ser != null) { ai.SetId(tvdbId, TVDoc.ProviderType.TheTVDB); return; } //Try removing any year string showNameNoYear = Regex.Replace(showName, @"\(\d{4}\)", "").Trim(); //Remove anything we can from hint to make it cleaner and hence more likely to match string refinedHint = FinderHelper.RemoveSeriesEpisodeIndicators(showNameNoYear, library.SeasonWords()); if (string.IsNullOrWhiteSpace(refinedHint)) { Logger.Info($"Ignoring {showName} as it refines to nothing."); } ser = TheTVDB.LocalCache.Instance.GetSeries(refinedHint, showErrorMsgBox, languageCode); ai.RefinedHint = refinedHint; if (ser != null) { ai.SetId(tvdbId, TVDoc.ProviderType.TheTVDB); } }
// note: "SeriesID" in a <Series> is the tv.com code, // "seriesid" in an <Episode> is the tvdb code! public SeriesInfo(ShowLibrary d, string name, int id) { mDoc = d; SetToDefaults(); Name = name; TvdbCode = id; }
public SeriesInfo(ShowLibrary d, string name, int id, string langCode) { mDoc = d; SetToDefaults(); TargetLanguageCode = langCode; Name = name; TvdbCode = id; }
public static void GuessShowItem([NotNull] FoundFolder ai, [NotNull] ShowLibrary library, bool showErrorMsgBox) { string showName = GuessShowName(ai, library); int tvdbId = FindShowCode(ai); if (string.IsNullOrEmpty(showName) && tvdbId == -1) { return; } if (tvdbId != -1) { try { SeriesInfo series = TheTVDB.Instance.GetSeriesAndDownload(tvdbId); if (series != null) { ai.TVDBCode = tvdbId; return; } } catch (ShowNotFoundException) { //continue to try the next method } } SeriesInfo ser = TheTVDB.Instance.GetSeries(showName, showErrorMsgBox); if (ser != null) { ai.TVDBCode = ser.TvdbCode; return; } //Try removing any year string showNameNoYear = Regex.Replace(showName, @"\(\d{4}\)", "").Trim(); //Remove anything we can from hint to make it cleaner and hence more likely to match string refinedHint = FinderHelper.RemoveSeriesEpisodeIndicators(showNameNoYear, library.SeasonWords()); if (string.IsNullOrWhiteSpace(refinedHint)) { Logger.Info($"Ignoring {showName} as it refines to nothing."); } ser = TheTVDB.Instance.GetSeries(refinedHint, showErrorMsgBox); ai.RefinedHint = refinedHint; if (ser != null) { ai.TVDBCode = ser.TvdbCode; } }
public SeriesInfo(ShowLibrary d, [NotNull] JObject json, JObject jsonInDefaultLang, int langId) { mDoc = d; SetToDefaults(); LanguageId = langId; LoadJson(json, jsonInDefaultLang); if (string.IsNullOrEmpty(Name)) { Logger.Warn("Issue with series " + TvdbCode); Logger.Warn(json.ToString()); Logger.Info(jsonInDefaultLang.ToString()); } }
private IEnumerable <ProcessedEpisode> ProcessedEpisodes() { List <ProcessedEpisode> pel = new List <ProcessedEpisode>(); if (mOriginalEps != null) { foreach (ProcessedEpisode pe in mOriginalEps) { pel.Add(new ProcessedEpisode(pe)); } ShowLibrary.ApplyRules(pel, workingRuleSet, show); } return(pel); }
public SeriesSpecifier(ShowLibrary d, int key, bool useCustomLanguage, [CanBeNull] string customLanguageCode, string name) { SeriesId = key; Name = name; doc = d; if (string.IsNullOrWhiteSpace(customLanguageCode)) { UseCustomLanguage = false; CustomLanguageCode = TVSettings.Instance.PreferredLanguageCode; } else { UseCustomLanguage = useCustomLanguage; CustomLanguageCode = customLanguageCode; } }
public static void GuessShowItem(FoundFolder ai, ShowLibrary library) { string showName = GuessShowName(ai, library); int tvdbId = FindShowCode(ai); if (string.IsNullOrEmpty(showName) && tvdbId == -1) { return; } TheTVDB.Instance.GetLock("GuessShowItem"); if (tvdbId != -1) { TheTVDB.Instance.Unlock("GuessShowItem"); SeriesInfo series = TheTVDB.Instance.GetSeriesAndDownload(tvdbId); if (series != null) { ai.TVDBCode = tvdbId; return; } } SeriesInfo ser = TheTVDB.Instance.GetSeries(showName); if (ser != null) { ai.TVDBCode = ser.TvdbCode; TheTVDB.Instance.Unlock("GuessShowItem"); return; } //Try removing any year string showNameNoYear = showName == null ? string.Empty:Regex.Replace(showName, @"\(\d{4}\)", "").Trim(); ser = TheTVDB.Instance.GetSeries(showNameNoYear); if (ser != null) { ai.TVDBCode = ser.TvdbCode; } TheTVDB.Instance.Unlock("GuessShowItem"); }
public static void GuessShowItem(FolderMonitorEntry ai, ShowLibrary library) { string showName = GuessShowName(ai, library); if (string.IsNullOrEmpty(showName)) { return; } TheTVDB.Instance.GetLock("GuessShowItem"); SeriesInfo ser = TheTVDB.Instance.GetSeries(showName); if (ser != null) { ai.TVDBCode = ser.TVDBCode; } TheTVDB.Instance.Unlock("GuessShowItem"); }
public TVDoc([CanBeNull] FileInfo settingsFile, CommandLineArgs args) { Args = args; Library = new ShowLibrary(); CurrentStats = new TVRenameStats(); actionManager = new ActionEngine(CurrentStats); cacheManager = new CacheUpdater(); localFinders = new FindMissingEpisodesLocally(this); downloadFinders = new FindMissingEpisodesDownloading(this); searchFinders = new FindMissingEpisodesSearch(this); mDirty = false; TheActionList = new ItemList(); scanProgDlg = null; downloadIdentifiers = new DownloadIdentifiersController(); LoadOk = (settingsFile is null || LoadXMLSettings(settingsFile)) && TheTVDB.Instance.LoadOk; }
private void FillPreview() { List <ProcessedEpisode> pel = new List <ProcessedEpisode>(); if (this.mOriginalEps != null) { foreach (ProcessedEpisode pe in this.mOriginalEps) { pel.Add(new ProcessedEpisode(pe)); } ShowLibrary.ApplyRules(pel, this.WorkingRuleSet, this.mSI); } this.lbEpsPreview.BeginUpdate(); this.lbEpsPreview.Items.Clear(); foreach (ProcessedEpisode pe in pel) { this.lbEpsPreview.Items.Add(this.NameStyle.NameFor(pe)); } this.lbEpsPreview.EndUpdate(); }
protected override void Check(ShowItem si, DirFilesCache dfc, TVDoc.ScanSettings settings) { if (settings.Token.IsCancellationRequested) { throw new TVRenameOperationInterruptedException(); } if (!TVSettings.Instance.AutoMergeLibraryEpisodes) { return; } Dictionary <int, List <string> > allFolders = si.AllExistngFolderLocations(); if (allFolders.Count == 0) // no folders defined for this show { return; // so, nothing to do. } int[] numbers = new int[si.SeasonEpisodes.Keys.Count]; si.SeasonEpisodes.Keys.CopyTo(numbers, 0); // process each folder for each season... foreach (int snum in numbers) { if (settings.Token.IsCancellationRequested) { throw new TVRenameOperationInterruptedException(); } if ((si.IgnoreSeasons.Contains(snum)) || (!allFolders.ContainsKey(snum))) { continue; // ignore/skip this season } if ((snum == 0) && (si.CountSpecials)) { continue; // don't process the specials season, as they're merged into the seasons themselves } if ((snum == 0) && TVSettings.Instance.IgnoreAllSpecials) { continue; } // all the folders for this particular season List <string> folders = allFolders[snum]; List <ProcessedEpisode> eps = si.SeasonEpisodes[snum]; List <ShowRule> rulesToAdd = new List <ShowRule>(); foreach (string folder in folders) { if (settings.Token.IsCancellationRequested) { throw new TVRenameOperationInterruptedException(); } FileInfo[] files = dfc.GetFiles(folder); if (files is null) { continue; } foreach (FileInfo fi in files) { if (settings.Token.IsCancellationRequested) { throw new TVRenameOperationInterruptedException(); } if (!fi.IsMovieFile()) { continue; //not a video file, so ignore } if (!FinderHelper.FindSeasEp(fi, out int seasNum, out int epNum, out int maxEp, si, out TVSettings.FilenameProcessorRE _)) { continue; // can't find season & episode, so this file is of no interest to us } if (seasNum == -1) { seasNum = snum; } int epIdx = eps.FindIndex(x => ((x.AppropriateEpNum == epNum) && (x.AppropriateSeasonNumber == seasNum))); if (epIdx == -1) { continue; // season+episode number don't correspond to any episode we know of from thetvdb } ProcessedEpisode ep = eps[epIdx]; if (ep.Type != ProcessedEpisode.ProcessedEpisodeType.merged && maxEp != -1) { LOGGER.Info( $"Looking at {ep.Show.ShowName} and have identified that episode {epNum} and {maxEp} of season {seasNum} should be merged into one file {fi.FullName}"); ShowRule sr = new ShowRule { DoWhatNow = RuleAction.kMerge, First = epNum, Second = maxEp }; rulesToAdd.Add(sr); } } // foreach file in folder } // for each folder for this season of this show foreach (ShowRule sr in rulesToAdd) { si.AddSeasonRule(snum, sr); LOGGER.Info($"Added new rule automatically for {sr}"); //Regenerate the episodes with the new rule added ShowLibrary.GenerateEpisodeDict(si); } } // for each season of this show }
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); }
public SeriesInfo(ShowLibrary d, [NotNull] XElement seriesXml) { mDoc = d; SetToDefaults(); LoadXml(seriesXml); }
public WhenToWatchViewModel() { lib = null; }
public WhenToWatchViewModel(ShowLibrary library) { lib = library; }
public MyShowsViewModel(ShowLibrary lib) { library = lib; }
private static void MergeShowEpisodes([NotNull] ShowItem si, DirFilesCache dfc, CancellationToken token, int snum, IEnumerable <string> folders) { if (snum == 0 && si.CountSpecials) { return; } if (snum == 0 && TVSettings.Instance.IgnoreAllSpecials) { return; } List <ProcessedEpisode> eps = si.SeasonEpisodes[snum]; List <ShowRule> rulesToAdd = new List <ShowRule>(); foreach (string folder in folders) { if (token.IsCancellationRequested) { throw new TVRenameOperationInterruptedException(); } FileInfo[] files = dfc.GetFiles(folder); if (files is null) { continue; } foreach (FileInfo fi in files) { if (token.IsCancellationRequested) { throw new TVRenameOperationInterruptedException(); } if (!fi.IsMovieFile()) { continue; //not a video file, so ignore } if (!FinderHelper.FindSeasEp(fi, out int seasNum, out int epNum, out int maxEp, si, out TVSettings.FilenameProcessorRE _)) { continue; // can't find season & episode, so this file is of no interest to us } if (seasNum == -1) { seasNum = snum; } int epIdx = eps.FindIndex(x => x.AppropriateEpNum == epNum && x.AppropriateSeasonNumber == seasNum); if (epIdx == -1) { continue; // season+episode number don't correspond to any episode we know of from thetvdb } ProcessedEpisode ep = eps[epIdx]; if (ep.Type == ProcessedEpisode.ProcessedEpisodeType.merged || maxEp == -1) { continue; } LOGGER.Info( $"Looking at {ep.Show.ShowName} and have identified that episode {epNum} and {maxEp} of season {seasNum} should be merged into one file {fi.FullName}"); ShowRule sr = new ShowRule { DoWhatNow = RuleAction.kMerge, First = epNum, Second = maxEp }; rulesToAdd.Add(sr); } // foreach file in folder } // for each folder for this season of this show foreach (ShowRule sr in rulesToAdd) { si.AddSeasonRule(snum, sr); LOGGER.Info($"Added new rule automatically for {sr}"); } if (rulesToAdd.Any()) { //Regenerate the episodes with the new rule added ShowLibrary.GenerateEpisodeDict(si); } }