private void CheckSeasonFolder(ShowItem si, DirFilesCache dfc, TVDoc.ScanSettings settings, int snum, bool timeForBannerUpdate, string folder) { if (settings.Token.IsCancellationRequested) { return; } if (TVSettings.Instance.NeedToDownloadBannerFile() && timeForBannerUpdate) { //Image series checks here Doc.TheActionList.Add( downloadIdentifiers.ForceUpdateSeason(DownloadIdentifier.DownloadType.downloadImage, si, folder, snum)); } //Image series checks here Doc.TheActionList.Add(downloadIdentifiers.ProcessSeason(si, folder, snum)); FileInfo[] files = dfc.GetFiles(folder); if (files is null) { return; } bool renCheck = TVSettings.Instance.RenameCheck && si.DoRename && Directory.Exists(folder); // renaming check needs the folder to exist bool missCheck = TVSettings.Instance.MissingCheck && si.DoMissingCheck; if (!renCheck && !missCheck) { return; } Dictionary <int, FileInfo> localEps = new Dictionary <int, FileInfo>(); int maxEpNumFound = 0; if (!si.SeasonEpisodes.ContainsKey(snum)) { return; } List <ProcessedEpisode> eps = si.SeasonEpisodes[snum]; foreach (FileInfo fi in files) { if (settings.Token.IsCancellationRequested) { return; } if (!FinderHelper.FindSeasEp(fi, out int seasNum, out int epNum, out int _, si, out TVSettings.FilenameProcessorRE _)) { continue; // can't find season & episode, so this file is of no interest to us } if (seasNum == -1) { seasNum = snum; } ProcessedEpisode ep = eps.Find(x => x.AppropriateEpNum == epNum && x.AppropriateSeasonNumber == seasNum); if (ep is null) { continue; // season+episode number don't correspond to any episode we know of from thetvdb } FileInfo actualFile = fi; // == RENAMING CHECK == if (renCheck && TVSettings.Instance.FileHasUsefulExtension(fi, true)) { // Note that the extension of the file may not be fi.extension as users can put ".mkv.t" for example as an extension string otherExtension = TVSettings.Instance.FileHasUsefulExtensionDetails(fi, true); string newName = TVSettings.Instance.FilenameFriendly( TVSettings.Instance.NamingStyle.NameFor(ep, otherExtension, folder.Length)); FileInfo fileWorthAdding = CheckFile(folder, fi, actualFile, newName, ep, files); if (fileWorthAdding != null) { localEps[epNum] = fileWorthAdding; } } // == MISSING CHECK part 1/2 == if (missCheck && fi.IsMovieFile()) { // first pass of missing check is to tally up the episodes we do have if (!localEps.ContainsKey(epNum)) { localEps[epNum] = actualFile; } if (epNum > maxEpNumFound) { maxEpNumFound = epNum; } } } // foreach file in folder // == MISSING CHECK part 2/2 (includes NFO and Thumbnails) == // look at the official list of episodes, and look to see if we have any gaps DateTime today = DateTime.Now; foreach (ProcessedEpisode dbep in eps) { if (!localEps.ContainsKey(dbep.AppropriateEpNum)) // not here locally { // second part of missing check is to see what is missing! if (missCheck) { DateTime?dt = dbep.GetAirDateDt(true); bool dtOk = dt != null; bool notFuture = (dtOk && (dt.Value.CompareTo(today) < 0)); // isn't an episode yet to be aired // only add to the missing list if, either: // - force check is on // - there are no aired dates at all, for up to and including this season // - there is an aired date, and it isn't in the future if (si.NoAirdatesUntilNow(snum) || ((si.ForceCheckFuture || notFuture) && dtOk) || (si.ForceCheckNoAirdate && !dtOk)) { // then add it as officially missing Doc.TheActionList.Add(new ItemMissing(dbep, folder)); } }// if doing missing check } else { if (settings.Type == TVSettings.ScanType.Full) { Doc.CurrentStats.NsNumberOfEpisodes++; } // do NFO and thumbnail checks if required FileInfo filo = localEps[dbep.AppropriateEpNum]; // filename (or future filename) of the file Doc.TheActionList.Add(downloadIdentifiers.ProcessEpisode(dbep, filo)); } } // up to date check, for each episode in thetvdb }