public void CheckFolders(CancellationToken token, [NotNull] SetProgressDelegate prog, bool detailedLogging, bool showErrorMsgBox) { // Check the folder list, and build up a new "AddItems" list. // guessing what the shows actually are isn't done here. That is done by // calls to "GuessShowItem" Logger.Info("*********************************************************************"); Logger.Info("*Starting to find folders that contain files, but are not in library*"); AddItems = new FolderMonitorEntryList(); int c = TVSettings.Instance.LibraryFolders.Count; int c2 = 0; foreach (string folder in TVSettings.Instance.LibraryFolders) { prog.Invoke(100 * c2++ / c, folder); DirectoryInfo di = new DirectoryInfo(folder); CheckFolderForShows(di, token, detailedLogging, showErrorMsgBox); if (token.IsCancellationRequested) { break; } } prog.Invoke(100, string.Empty); }
private void Check(SetProgressDelegate?progress, int startpct, int totPct) { startPosition = startpct; endPosition = totPct; progressDelegate = progress; progressDelegate?.Invoke(startpct, string.Empty); try { if (!Active()) { return; } DoCheck(progress); LogActionListSummary(); } catch (TVRenameOperationInterruptedException) { throw; } catch (Exception e) { LOGGER.Fatal(e, $"Failed to run Scan for {ActivityName()}"); } finally { progressDelegate?.Invoke(totPct, string.Empty); } }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { int c = this.TheActionList.Count + 2; int n = 1; prog.Invoke(100 * n / c); RSSItemList RSSList = new RSSItemList(); foreach (string s in TVSettings.Instance.RSSURLs) { RSSList.DownloadRSS(s, TVSettings.Instance.FNPRegexs); } ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); foreach (Item Action1 in this.TheActionList) { if (this.ActionCancel) { return; } n++; prog.Invoke(100 * n / c); if (!(Action1 is ItemMissing)) { continue; } ItemMissing Action = (ItemMissing)(Action1); ProcessedEpisode pe = Action.Episode; string simpleShowName = Helpers.SimplifyName(pe.SI.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheSeries.Name); foreach (RSSItem rss in RSSList) { if ((FileHelper.SimplifyAndCheckFilename(rss.ShowName, simpleShowName, true, false) || (string.IsNullOrEmpty(rss.ShowName) && FileHelper.SimplifyAndCheckFilename(rss.Title, simpleSeriesName, true, false))) && (rss.Season == pe.SeasonNumber) && (rss.Episode == pe.EpNum)) { newItems.Add(new ActionRSS(rss, Action.TheFileNoExt, pe)); toRemove.Add(Action1); } } } foreach (Item i in toRemove) { this.TheActionList.Remove(i); } foreach (Item Action in newItems) { this.TheActionList.Add(Action); } prog.Invoke(100); }
protected void SearchForAppropriateDownloads(SetProgressDelegate prog, int startpct, int totPct, List <TorrentEntry> downloading, DownloadApp tApp) { ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = ActionList.Count + 2; int n = 1; prog.Invoke(startpct); foreach (ItemMissing action in ActionList.MissingItems()) { if (ActionCancel) { return; } prog.Invoke(startpct + ((totPct - startpct) * (++n) / (c))); foreach (TorrentEntry te in downloading) { FileInfo file = new FileInfo(te.DownloadingTo); if (!TVSettings.Instance.UsefulExtension(file.Extension, false)) // not a usefile file extension { continue; } //do any of the possible names for the series match the filename? bool matched = (action.Episode.Show.GetSimplifiedPossibleShowNames().Any(name => FileHelper.SimplifyAndCheckFilename(file.FullName, name))); if (!matched) { continue; } if (TVDoc.FindSeasEp(file, out int seasF, out int epF, out int _, action.Episode.Show) && (seasF == action.Episode.AppropriateSeasonNumber) && (epF == action.Episode.AppropriateEpNum)) { toRemove.Add(action); newList.Add(new ItemDownloading(te, action.Episode, action.TheFileNoExt, tApp)); break; } } } foreach (Item i in toRemove) { ActionList.Remove(i); } foreach (Item action in newList) { ActionList.Add(action); } prog.Invoke(totPct); }
private int BuildDirCache(SetProgressDelegate prog, int count, int totalFiles, string folder, bool subFolders) { if (!Directory.Exists(folder)) { logger.Error("The search folder \"" + folder + " does not exist."); return(count); } try { /* * if (folder.Length >= 248) * * { * logger.Error ("Skipping folder that has a name longer than the Windows permitted 247 characters: " + folder); * return count; * } * */ DirectoryInfo di = new DirectoryInfo(folder); if (!di.Exists) { return(count); } // DirectorySecurity ^ds = di->GetAccessControl(); FileInfo[] f2 = di.GetFiles(); foreach (FileInfo ff in f2) { count++; // if ((ff.Name.Length + folder.Length) >= 260) // logger.Error("Skipping file that has a path+name longer than the Windows permitted 259 characters: " + ff.Name + " in " + folder); // else this.Add(new DirCacheEntry(ff)); if ((prog != null) && (totalFiles != 0)) { prog.Invoke(100 * (count) / totalFiles); } } if (subFolders) { DirectoryInfo[] dirs = di.GetDirectories(); foreach (DirectoryInfo di2 in dirs) { count = this.BuildDirCache(prog, count, totalFiles, di2.FullName, subFolders); } } } catch (UnauthorizedAccessException e) { logger.Info(e); } catch (Exception exception) { logger.Error(exception); } return(count); }
private int BuildDirCache(SetProgressDelegate prog, int count, int totalFiles, string folder, bool subFolders) { if (!Directory.Exists(folder)) { MessageBox.Show("The search folder \"" + folder + " does not exist.\n", "Folder does not exist", MessageBoxButtons.OK, MessageBoxIcon.Warning); return(count); } try { if (folder.Length >= 248) { MessageBox.Show("Skipping folder that has a name longer than the Windows permitted 247 characters: " + folder, "Path name too long", MessageBoxButtons.OK, MessageBoxIcon.Warning); return(count); } DirectoryInfo di = new DirectoryInfo(folder); if (!di.Exists) { return(count); } // DirectorySecurity ^ds = di->GetAccessControl(); FileInfo[] f2 = di.GetFiles(); foreach (FileInfo ff in f2) { count++; if ((ff.Name.Length + folder.Length) >= 260) { MessageBox.Show("Skipping file that has a path+name longer than the Windows permitted 259 characters: " + ff.Name + " in " + folder, "File+Path name too long", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { this.Add(new DirCacheEntry(ff)); } if ((prog != null) && (totalFiles != 0)) { prog.Invoke(100 * (count) / totalFiles); } } if (subFolders) { DirectoryInfo[] dirs = di.GetDirectories(); foreach (DirectoryInfo di2 in dirs) { count = this.BuildDirCache(prog, count, totalFiles, di2.FullName, subFolders); } } } catch (UnauthorizedAccessException) { } catch { } return(count); }
private int BuildDirCache(SetProgressDelegate prog, int count, int totalFiles, string folder, bool subFolders) { if (!Directory.Exists(folder)) { Logger.Error("The search folder \"" + folder + " does not exist."); return(count); } try { DirectoryInfo di = new DirectoryInfo(folder); if (!di.Exists) { return(count); } FileInfo[] f2 = di.GetFiles(); foreach (FileInfo ff in f2) { count++; Add(new DirCacheEntry(ff)); if ((prog != null) && (totalFiles != 0)) { prog.Invoke(100 * (count) / totalFiles); } } if (subFolders) { DirectoryInfo[] dirs = di.GetDirectories(); foreach (DirectoryInfo di2 in dirs) { count += BuildDirCache(prog, count, totalFiles, di2.FullName, true); } } } catch (UnauthorizedAccessException e) { Logger.Info(e); } catch (Exception exception) { Logger.Error(exception); } return(count); }
private int BuildDirCache(SetProgressDelegate prog, int count, int totalFiles, string folder, bool subFolders) { if (!Directory.Exists(folder)) { Logger.Warn("The search folder \"" + folder + " does not exist."); return(count); } try { DirectoryInfo di = new DirectoryInfo(folder); if (!di.Exists) { return(count); } foreach (FileInfo ff in GetFiles(di)) { count++; Add(new DirCacheEntry(ff)); if (prog != null && totalFiles != 0) { prog.Invoke(100 * count / totalFiles, string.Empty); } } if (subFolders) { foreach (DirectoryInfo di2 in GetDirectoryInfo(di)) { count += BuildDirCache(prog, count, totalFiles, di2.FullName, true); } } } catch (Exception exception) { Logger.Error(exception); } return(count); }
public void CheckAgainstSABnzbd(SetProgressDelegate prog, int startpct, int totPct) { if (String.IsNullOrEmpty(Settings.SABAPIKey) || String.IsNullOrEmpty(Settings.SABHostPort)) { prog.Invoke(startpct + 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://" + Settings.SABHostPort + "/sabnzbd/api?mode=queue&start=0&limit=8888&output=xml&apikey=" + Settings.SABAPIKey; WebClient wc = new WebClient(); byte[] r = null; try { r = wc.DownloadData(theURL); } catch (WebException) { } if (r == null) { prog.Invoke(startpct + totPct); return; } try { SAB.result res = SAB.result.Deserialize(r); if (res.status == "False") { MessageBox.Show(res.error, "SABnzbd Queue Check", MessageBoxButtons.OK, MessageBoxIcon.Error); prog.Invoke(startpct + totPct); return; } } catch { // wasn't a result/error combo. this is good! } SAB.queue sq = null; try { sq = SAB.queue.Deserialize(r); } catch (Exception) { MessageBox.Show("Error processing data from SABnzbd", "SABnzbd Queue Check", MessageBoxButtons.OK, MessageBoxIcon.Error); prog.Invoke(startpct + totPct); return; } System.Diagnostics.Debug.Assert(sq != null); // shouldn't happen if (sq == null || sq.slots==null || sq.slots.Length == 0) // empty queue return; ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = this.TheActionList.Count + 2; int n = 1; foreach (Item Action1 in this.TheActionList) { if (this.ActionCancel) return; n++; prog.Invoke(startpct + totPct * 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 (!this.Settings.UsefulExtension(file.Extension, false)) // not a usefile file extension // continue; if (this.SimplifyAndCheckFilename(file.FullName, showname, true, false)) // if (Regex::Match(simplifiedfname,"\\b"+showname+"\\b",RegexOptions::IgnoreCase)->Success) { int seasF; int epF; if (this.FindSeasEp(file, out seasF, out epF, Action.Episode.SI) && (seasF == Action.Episode.SeasonNumber) && (epF == Action.Episode.EpNum)) { toRemove.Add(Action1); newList.Add(new ItemSABnzbd(te, Action.Episode, Action.TheFileNoExt)); break; } } } } } foreach (Item i in toRemove) this.TheActionList.Remove(i); foreach (Item Action in newList) this.TheActionList.Add(Action); prog.Invoke(startpct+totPct); }
public void RSSSearch(SetProgressDelegate prog) { int c = this.TheActionList.Count + 2; int n = 1; prog.Invoke(100 * n / c); this.RSSList = new RSSItemList(); foreach (string s in this.Settings.RSSURLs) this.RSSList.DownloadRSS(s, this.Settings.FNPRegexs); ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); foreach (Item Action1 in this.TheActionList) { if (this.ActionCancel) return; n++; prog.Invoke(100 * n / c); if (!(Action1 is ItemMissing)) continue; ItemMissing Action = (ItemMissing) (Action1); ProcessedEpisode pe = Action.Episode; string simpleShowName = Helpers.SimplifyName(pe.SI.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheSeries.Name); foreach (RSSItem rss in this.RSSList) { if ((this.SimplifyAndCheckFilename(rss.ShowName, simpleShowName, true, false) || (string.IsNullOrEmpty(rss.ShowName) && this.SimplifyAndCheckFilename(rss.Title, simpleSeriesName, true, false))) && (rss.Season == pe.SeasonNumber) && (rss.Episode == pe.EpNum)) { newItems.Add(new ActionRSS(rss, Action.TheFileNoExt, pe)); toRemove.Add(Action1); } } } foreach (Item i in toRemove) this.TheActionList.Remove(i); foreach (Item Action in newItems) this.TheActionList.Add(Action); prog.Invoke(100); }
public void RenameAndMissingCheck(SetProgressDelegate prog, List<ShowItem> showList) { this.TheActionList = new ItemList(); //int totalEps = 0; this.LockShowItems(); if (showList == null) showList = ShowItems; //foreach (ShowItem si in showlist) // if (si.DoRename) // totalEps += si.SeasonEpisodes.Count; if (this.Settings.RenameCheck) this.Stats().RenameChecksDone++; if (this.Settings.MissingCheck) this.Stats().MissingChecksDone++; prog.Invoke(0); if (showList == null) // only do episode count if we're doing all shows and seasons this.mStats.NS_NumberOfEpisodes = 0; int c = 0; foreach (ShowItem si in showList) { if (this.ActionCancel) return; System.Diagnostics.Debug.Print(DateTime.Now.ToLongTimeString()+ " Rename and missing check: " + si.ShowName); c++; prog.Invoke(100 * c / showList.Count); if (si.AllFolderLocations(this.Settings).Count == 0) // no folders defined for this show continue; // so, nothing to do. // for each tv show, optionally write a tvshow.nfo file if (this.Settings.NFOs && !string.IsNullOrEmpty(si.AutoAdd_FolderBase) && (si.AllFolderLocations(this.Settings).Count > 0)) { FileInfo tvshownfo = Helpers.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> ? needUpdate = needUpdate || (tvshownfo.LastWriteTime.ToUniversalTime().CompareTo(new DateTime(2009, 9, 13, 7, 30, 0, 0, DateTimeKind.Utc)) < 0); if (needUpdate) this.TheActionList.Add(new ActionNFO(tvshownfo, si)); } // process each folder for each season... int[] numbers = new int[si.SeasonEpisodes.Keys.Count]; si.SeasonEpisodes.Keys.CopyTo(numbers, 0); Dictionary<int, List<string>> allFolders = si.AllFolderLocations(this.Settings); int lastSeason = 0; foreach (int n in numbers) if (n > lastSeason) lastSeason = n; foreach (int snum in numbers) { if (this.ActionCancel) return; 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 // all the folders for this particular season List<string> folders = allFolders[snum]; bool folderNotDefined = (folders.Count == 0); if (folderNotDefined && (this.Settings.MissingCheck && !si.AutoAddNewSeasons)) continue; // folder for the season is not defined, and we're not auto-adding it List<ProcessedEpisode> eps = si.SeasonEpisodes[snum]; int maxEpisodeNumber = 0; foreach (ProcessedEpisode episode in eps) { if (episode.EpNum > maxEpisodeNumber) maxEpisodeNumber = episode.EpNum; } List<string> doneFolderJPG = new List<String>(); if (this.Settings.FolderJpg) { // main image for the folder itself // base folder: if (!string.IsNullOrEmpty(si.AutoAdd_FolderBase) && (si.AllFolderLocations(this.Settings, false).Count > 0)) { FileInfo fi = Helpers.FileInFolder(si.AutoAdd_FolderBase, "folder.jpg"); if (!fi.Exists) { string bannerPath = si.TheSeries().GetItem(this.Settings.ItemForFolderJpg()); if (!string.IsNullOrEmpty(bannerPath)) this.TheActionList.Add(new ActionDownload(si, null, fi, bannerPath)); } doneFolderJPG.Add(si.AutoAdd_FolderBase); } } foreach (string folder in folders) { if (this.ActionCancel) return; // generate new filename info DirectoryInfo di; try { di = new DirectoryInfo(folder); } catch { continue; } bool renCheck = this.Settings.RenameCheck && si.DoRename && di.Exists; // renaming check needs the folder to exist bool missCheck = this.Settings.MissingCheck && si.DoMissingCheck; if (this.Settings.FolderJpg) { // season folders JPGs if (!doneFolderJPG.Contains(folder)) // some folders may come up multiple times { doneFolderJPG.Add(folder); FileInfo fi = Helpers.FileInFolder(folder, "folder.jpg"); if (!fi.Exists) { string bannerPath = si.TheSeries().GetItem(this.Settings.ItemForFolderJpg()); if (!string.IsNullOrEmpty(bannerPath)) this.TheActionList.Add(new ActionDownload(si, null, fi, bannerPath)); } } } FileInfo[] files = di.GetFiles(); // all the files in the folder FileInfo[] localEps = new FileInfo[maxEpisodeNumber + 1]; int maxEpNumFound = 0; if (!renCheck && !missCheck) continue; foreach (FileInfo fi in files) { if (this.ActionCancel) return; int seasNum; int epNum; if (!this.FindSeasEp(fi, out seasNum, out epNum, si)) continue; // can't find season & episode, so this file is of no interest to us if (seasNum == -1) seasNum = snum; #if !NOLAMBDA int epIdx = eps.FindIndex(x => ((x.EpNum == epNum) && (x.SeasonNumber == seasNum))); if (epIdx == -1) continue; // season+episode number don't correspond to any episode we know of from thetvdb ProcessedEpisode ep = eps[epIdx]; #else // equivalent of the 4 lines above, if compiling on MonoDevelop on Windows which, for // some reason, doesn't seem to support lambda functions (the => thing) ProcessedEpisode ep = null; foreach (ProcessedEpisode x in eps) { if (((x.EpNum == epNum) && (x.SeasonNumber == seasNum))) { ep = x; break; } } if (ep == null) continue; // season+episode number don't correspond to any episode we know of from thetvdb #endif FileInfo actualFile = fi; if (renCheck && this.Settings.UsefulExtension(fi.Extension, true)) // == RENAMING CHECK == { string newname = this.Settings.FilenameFriendly(this.Settings.NamingStyle.NameForExt(ep, fi.Extension, folder.Length)); if (newname != actualFile.Name) { actualFile = Helpers.FileInFolder(folder, newname); // rename updates the filename this.TheActionList.Add(new ActionCopyMoveRename(ActionCopyMoveRename.Op.Rename, fi, actualFile, ep)); } } if (missCheck && this.Settings.UsefulExtension(fi.Extension, false)) // == MISSING CHECK part 1/2 == { // first pass of missing check is to tally up the episodes we do have localEps[epNum] = actualFile; if (epNum > maxEpNumFound) maxEpNumFound = epNum; } } // foreach file in folder if (missCheck) // == MISSING CHECK part 2/2 (includes NFO and Thumbnails) == { // second part of missing check is to see what is missing! // look at the offical list of episodes, and look to see if we have any gaps DateTime today = DateTime.Now; TheTVDB db = this.GetTVDB(true, "UpToDateCheck"); foreach (ProcessedEpisode dbep in eps) { if ((dbep.EpNum > maxEpNumFound) || (localEps[dbep.EpNum] == null)) // not here locally { 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 bool noAirdatesUntilNow = true; // for specials "season", see if any season has any airdates // otherwise, check only up to the season we are considering for (int i = 1; i <= ((snum == 0) ? lastSeason : snum); i++) { if (this.HasAnyAirdates(si, i)) { noAirdatesUntilNow = false; break; } } // only add to the missing list if, either: // - force check is on // - there are no airdates at all, for up to and including this season // - there is an airdate, and it isn't in the future if (noAirdatesUntilNow || ((si.ForceCheckFuture || notFuture) && dtOK) || (si.ForceCheckNoAirdate && !dtOK)) { // then add it as officially missing this.TheActionList.Add(new ItemMissing(dbep, folder + System.IO.Path.DirectorySeparatorChar + this.Settings.FilenameFriendly(this.Settings.NamingStyle.NameForExt(dbep, null, folder.Length)))); } } else { // the file is here if (showList == null) this.mStats.NS_NumberOfEpisodes++; // do NFO and thumbnail checks if required FileInfo filo = localEps[dbep.EpNum]; // filename (or future filename) of the file this.ThumbnailAndNFOCheck(dbep, filo, this.TheActionList); } } // up to date check, for each episode in thetvdb db.Unlock("UpToDateCheck"); } // if doing missing check } // for each folder for this season of this show } // for each season of this show } // for each show this.UnlockShowItems(); this.RemoveIgnored(); }
public void LookForMissingEps(SetProgressDelegate prog) { // for each ep we have noticed as being missing // look through the monitored folders for it this.Stats().FindAndOrganisesDone++; prog.Invoke(0); ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int fileCount = 0; foreach (string s in this.SearchFolders) fileCount += DirCache.CountFiles(s, true); int c = 0; DirCache dirCache = new DirCache(); foreach (String s in this.SearchFolders) { if (this.ActionCancel) return; c = dirCache.AddFolder(prog, c, fileCount, s, true, this.Settings); } c = 0; int totalN = this.TheActionList.Count; foreach (Item action1 in this.TheActionList) { if (this.ActionCancel) return; prog.Invoke(50 + 50 * (++c) / (totalN + 1)); // second 50% of progress bar if (action1 is ItemMissing) { if (this.FindMissingEp(dirCache, (ItemMissing) (action1), newList, ActionCopyMoveRename.Op.Copy)) toRemove.Add(action1); } } if (this.Settings.KeepTogether) this.KeepTogether(newList); prog.Invoke(100); if (!this.Settings.LeaveOriginals) { // go through and change last of each operation on a given source file to a 'Move' // ideally do that move within same filesystem // sort based on source file, and destination drive, putting last if destdrive == sourcedrive newList.Sort(new ActionItemSorter()); // sort puts all the CopyMoveRenames together // then set the last of each source file to be a move for (int i = 0; i < newList.Count; i++) { ActionCopyMoveRename cmr1 = newList[i] as ActionCopyMoveRename; bool ok1 = cmr1 != null; if (!ok1) continue; bool last = i == (newList.Count - 1); ActionCopyMoveRename cmr2 = !last ? newList[i + 1] as ActionCopyMoveRename : null; bool ok2 = cmr2 != null; if (ok2) { ActionCopyMoveRename a1 = cmr1; ActionCopyMoveRename a2 = cmr2; if (!Helpers.Same(a1.From, a2.From)) a1.Operation = ActionCopyMoveRename.Op.Move; } else { // last item, or last copymoverename item in the list ActionCopyMoveRename a1 = cmr1; a1.Operation = ActionCopyMoveRename.Op.Move; } } } foreach (Item i in toRemove) this.TheActionList.Remove(i); foreach (Item i in newList) this.TheActionList.Add(i); // if (Settings->ExportFOXML) // ExportFOXML(Settings->ExportFOXMLTo); }
protected void UpdateStatus(int recordNumber, int totalRecords, string message) { int position = (endPosition - startPosition) * recordNumber / (totalRecords + 1); progressDelegate?.Invoke(startPosition + position, message); }
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; byte[] r = DownloadPage(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; 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 = ActionList.Count + 2; int n = 1; foreach (ItemMissing action in ActionList.MissingItems()) { if (ActionCancel) { return; } prog.Invoke(startpct + ((totPct - startpct) * (++n) / (c))); string showname = Helpers.SimplifyName(action.Episode.Show.ShowName); foreach (SAB.QueueSlotsSlot te in sq.slots) { FileInfo file = new FileInfo(te.filename); if (!FileHelper.SimplifyAndCheckFilename(file.FullName, showname, true, false)) { continue; } if (!TVDoc.FindSeasEp(file, out int seasF, out int epF, out int _, action.Episode.Show) || (seasF != action.Episode.AppropriateSeasonNumber) || (epF != action.Episode.AppropriateEpNum)) { continue; } toRemove.Add(action); newList.Add(new ItemDownloading(te, action.Episode, action.TheFileNoExt, DownloadApp.SABnzbd)); break; } } foreach (Item i in toRemove) { ActionList.Remove(i); } foreach (Item action in newList) { ActionList.Add(action); } prog.Invoke(totPct); }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { if (String.IsNullOrEmpty(TVSettings.Instance.SABAPIKey) || String.IsNullOrEmpty(TVSettings.Instance.SABHostPort)) { prog.Invoke(startpct + 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) { } if (r == null) { prog.Invoke(startpct + totPct); return; } try { SAB.result res = SAB.result.Deserialize(r); if (res.status == "False") { MessageBox.Show(res.error, "SABnzbd Queue Check", MessageBoxButtons.OK, MessageBoxIcon.Error); prog.Invoke(startpct + totPct); return; } } catch { // wasn't a result/error combo. this is good! } SAB.queue sq = null; try { sq = SAB.queue.Deserialize(r); } catch (Exception) { MessageBox.Show("Error processing data from SABnzbd", "SABnzbd Queue Check", MessageBoxButtons.OK, MessageBoxIcon.Error); prog.Invoke(startpct + totPct); return; } System.Diagnostics.Debug.Assert(sq != null); // shouldn't happen if (sq == null || sq.slots == null || sq.slots.Length == 0) // empty queue { return; } ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = this.TheActionList.Count + 2; int n = 1; foreach (Item Action1 in this.TheActionList) { if (this.ActionCancel) { return; } n++; prog.Invoke(startpct + totPct * 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)) // if (Regex::Match(simplifiedfname,"\\b"+showname+"\\b",RegexOptions::IgnoreCase)->Success) { int seasF; int epF; if (TVDoc.FindSeasEp(file, out seasF, out epF, Action.Episode.SI) && (seasF == Action.Episode.SeasonNumber) && (epF == Action.Episode.EpNum)) { toRemove.Add(Action1); newList.Add(new ItemSABnzbd(te, Action.Episode, Action.TheFileNoExt)); break; } } } } } foreach (Item i in toRemove) { this.TheActionList.Remove(i); } foreach (Item Action in newList) { this.TheActionList.Add(Action); } prog.Invoke(startpct + totPct); }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { // get list of files being downloaded by uTorrent string resDatFile = TVSettings.Instance.ResumeDatPath; if (string.IsNullOrEmpty(resDatFile) || !File.Exists(resDatFile)) { return; } BTResume btr = new BTResume(prog, resDatFile); if (!btr.LoadResumeDat()) { return; } List <TorrentEntry> downloading = btr.AllFilesBeingDownloaded(); ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = this.TheActionList.Count + 2; int n = 1; prog.Invoke(startpct + totPct * n / c); foreach (Item Action1 in this.TheActionList) { if (this.ActionCancel) { return; } n++; prog.Invoke(100 * n / c); if (!(Action1 is ItemMissing)) { continue; } ItemMissing Action = (ItemMissing)(Action1); string showname = Helpers.SimplifyName(Action.Episode.SI.ShowName); foreach (TorrentEntry te in downloading) { FileInfo file = new FileInfo(te.DownloadingTo); if (!TVSettings.Instance.UsefulExtension(file.Extension, false)) // not a usefile file extension { continue; } if (FileHelper.SimplifyAndCheckFilename(file.FullName, showname, true, false)) // if (Regex::Match(simplifiedfname,"\\b"+showname+"\\b",RegexOptions::IgnoreCase)->Success) { int seasF; int epF; if (TVDoc.FindSeasEp(file, out seasF, out epF, Action.Episode.SI) && (seasF == Action.Episode.SeasonNumber) && (epF == Action.Episode.EpNum)) { toRemove.Add(Action1); newList.Add(new ItemuTorrenting(te, Action.Episode, Action.TheFileNoExt)); break; } } } } foreach (Item i in toRemove) { this.TheActionList.Remove(i); } foreach (Item Action in newList) { this.TheActionList.Add(Action); } prog.Invoke(startpct + totPct); }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { int c = this.ActionList.Count + 2; int n = 1; prog.Invoke(startpct); // ReSharper disable once InconsistentNaming RSSItemList RSSList = new RSSItemList(); foreach (string s in TVSettings.Instance.RSSURLs) { RSSList.DownloadRSS(s, TVSettings.Instance.FNPRegexs); } ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); foreach (Item testItem in this.ActionList) { if (this.ActionCancel) { return; } prog.Invoke(startpct + (totPct - startpct) * (++n) / (c)); if (!(testItem is ItemMissing action)) { continue; } ProcessedEpisode pe = action.Episode; string simpleShowName = Helpers.SimplifyName(pe.SI.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheSeries.Name); foreach (RSSItem rss in RSSList) { if ( !FileHelper.SimplifyAndCheckFilename(rss.ShowName, simpleShowName, true, false) && !( string.IsNullOrEmpty(rss.ShowName) && FileHelper.SimplifyAndCheckFilename(rss.Title, simpleSeriesName, true, false) ) ) { continue; } if (rss.Season != pe.AppropriateSeasonNumber) { continue; } if (rss.Episode != pe.AppropriateEpNum) { continue; } Logger.Info($"Adding {rss.URL} as it appears to be match for {testItem.Episode.SI.ShowName} S{testItem.Episode.AppropriateSeasonNumber}E{testItem.Episode.AppropriateEpNum}"); newItems.Add(new ActionRSS(rss, action.TheFileNoExt, pe)); toRemove.Add(testItem); } } //We now want to rationlise the newItems - just in case we've added duplicates List <ActionRSS> duplicateActionRSS = new List <ActionRSS>(); foreach (Item x in newItems) { if (!(x is ActionRSS testActionRSSOne)) { continue; } foreach (Item y in newItems) { if (!(y is ActionRSS testActionRSSTwo)) { continue; } if (x.Equals(y)) { continue; } string[] preferredTerms = TVSettings.Instance.PreferredRSSSearchTerms(); if (testActionRSSOne.RSS.ShowName.ContainsOneOf(preferredTerms) && !testActionRSSTwo.RSS.ShowName.ContainsOneOf(preferredTerms)) { duplicateActionRSS.Add(testActionRSSTwo); Logger.Info($"Removing {testActionRSSTwo.RSS.URL} as it is not as good a match as {testActionRSSOne.RSS.URL }"); } if (testActionRSSOne.RSS.Title.ContainsOneOf(preferredTerms) && !testActionRSSTwo.RSS.Title.ContainsOneOf(preferredTerms)) { duplicateActionRSS.Add(testActionRSSTwo); Logger.Info( $"Removing {testActionRSSTwo.RSS.URL} as it is not as good a match as {testActionRSSOne.RSS.URL}"); } } } foreach (ActionRSS x in duplicateActionRSS) { newItems.Remove(x); } foreach (Item i in toRemove) { this.ActionList.Remove(i); } foreach (Item action in newItems) { this.ActionList.Add(action); } prog.Invoke(totPct); }
public void RenameAndMissingCheck(SetProgressDelegate prog, List<ShowItem> showList) { this.TheActionList = new ItemList(); //int totalEps = 0; this.LockShowItems(); if (showList == null) showList = ShowItems; //foreach (ShowItem si in showlist) // if (si.DoRename) // totalEps += si.SeasonEpisodes.Count; if (TVSettings.Instance.RenameCheck) this.Stats().RenameChecksDone++; if (TVSettings.Instance.MissingCheck) this.Stats().MissingChecksDone++; prog.Invoke(0); if (showList == null) // only do episode count if we're doing all shows and seasons this.mStats.NS_NumberOfEpisodes = 0; DirFilesCache dfc = new DirFilesCache(); int c = 0; foreach (ShowItem si in showList) { if (this.ActionCancel) return; System.Diagnostics.Debug.Print(DateTime.Now.ToLongTimeString()+ " Rename and missing check: " + si.ShowName); c++; prog.Invoke(100 * c / showList.Count); if (si.AllFolderLocations().Count == 0) // no folders defined for this show continue; // so, nothing to do. //This is the code that will iterate over the DownloadIdentifiers and ask each to ensure that //it has all the required files for that show if (!string.IsNullOrEmpty(si.AutoAdd_FolderBase) && (si.AllFolderLocations().Count > 0)) { this.TheActionList.Add(DownloadIdentifiers.ProcessShow(si)); } //MS_TODO Put the bannerrefresh period into the settings file, we'l default to 3 months DateTime cutOff = System.DateTime.Now.AddMonths(-3); DateTime lastUpdate = si.BannersLastUpdatedOnDisk ?? System.DateTime.Now.AddMonths(-4); bool timeForBannerUpdate = (cutOff.CompareTo(lastUpdate) == 1); if (TVSettings.Instance.NeedToDownloadBannerFile() && timeForBannerUpdate) { this.TheActionList.Add(DownloadIdentifiers.ForceUpdateShow(DownloadIdentifier.DownloadType.downloadImage, si)); si.BannersLastUpdatedOnDisk = DateTime.Now; this.SetDirty(); } // process each folder for each season... int[] numbers = new int[si.SeasonEpisodes.Keys.Count]; si.SeasonEpisodes.Keys.CopyTo(numbers, 0); Dictionary<int, List<string>> allFolders = si.AllFolderLocations(); int lastSeason = 0; foreach (int n in numbers) if (n > lastSeason) lastSeason = n; foreach (int snum in numbers) { if (this.ActionCancel) return; 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 // all the folders for this particular season List<string> folders = allFolders[snum]; bool folderNotDefined = (folders.Count == 0); if (folderNotDefined && (TVSettings.Instance.MissingCheck && !si.AutoAddNewSeasons)) continue; // folder for the season is not defined, and we're not auto-adding it List<ProcessedEpisode> eps = si.SeasonEpisodes[snum]; int maxEpisodeNumber = 0; foreach (ProcessedEpisode episode in eps) { if (episode.EpNum > maxEpisodeNumber) maxEpisodeNumber = episode.EpNum; } // base folder: if (!string.IsNullOrEmpty(si.AutoAdd_FolderBase) && (si.AllFolderLocations(false).Count > 0)) { // main image for the folder itself this.TheActionList.Add(DownloadIdentifiers.ProcessShow(si)); } foreach (string folder in folders) { if (this.ActionCancel) return; FileInfo[] files = dfc.Get(folder); if (files == null) continue; if (TVSettings.Instance.NeedToDownloadBannerFile() && timeForBannerUpdate) { //Image series checks here this.TheActionList.Add(DownloadIdentifiers.ForceUpdateSeason(DownloadIdentifier.DownloadType.downloadImage, si, folder, snum)); } bool renCheck = TVSettings.Instance.RenameCheck && si.DoRename && Directory.Exists(folder); // renaming check needs the folder to exist bool missCheck = TVSettings.Instance.MissingCheck && si.DoMissingCheck; //Image series checks here this.TheActionList.Add(DownloadIdentifiers.ProcessSeason(si,folder,snum)); FileInfo[] localEps = new FileInfo[maxEpisodeNumber + 1]; int maxEpNumFound = 0; if (!renCheck && !missCheck) continue; foreach (FileInfo fi in files) { if (this.ActionCancel) return; int seasNum; int epNum; if (!FindSeasEp(fi, out seasNum, out epNum, si)) continue; // can't find season & episode, so this file is of no interest to us if (seasNum == -1) seasNum = snum; #if !NOLAMBDA int epIdx = eps.FindIndex(x => ((x.EpNum == epNum) && (x.SeasonNumber == seasNum))); if (epIdx == -1) continue; // season+episode number don't correspond to any episode we know of from thetvdb ProcessedEpisode ep = eps[epIdx]; #else // equivalent of the 4 lines above, if compiling on MonoDevelop on Windows which, for // some reason, doesn't seem to support lambda functions (the => thing) ProcessedEpisode ep = null; foreach (ProcessedEpisode x in eps) { if (((x.EpNum == epNum) && (x.SeasonNumber == seasNum))) { ep = x; break; } } if (ep == null) continue; // season+episode number don't correspond to any episode we know of from thetvdb #endif FileInfo actualFile = fi; if (renCheck && TVSettings.Instance.UsefulExtension(fi.Extension, true)) // == RENAMING CHECK == { string newname = TVSettings.Instance.FilenameFriendly(TVSettings.Instance.NamingStyle.NameForExt(ep, fi.Extension, folder.Length)); if (newname != actualFile.Name) { actualFile = FileHelper.FileInFolder(folder, newname); // rename updates the filename this.TheActionList.Add(new ActionCopyMoveRename(ActionCopyMoveRename.Op.Rename, fi, actualFile, ep, null)); //The following section informs the DownloadIdentifers that we already plan to //copy a file inthe appropriate place and they do not need to worry about downloading //one for that purpse DownloadIdentifiers.notifyComplete(actualFile); } } if (missCheck && TVSettings.Instance.UsefulExtension(fi.Extension, false)) // == MISSING CHECK part 1/2 == { // first pass of missing check is to tally up the episodes we do have localEps[epNum] = actualFile; if (epNum > maxEpNumFound) maxEpNumFound = epNum; } } // foreach file in folder if (missCheck) // == MISSING CHECK part 2/2 (includes NFO and Thumbnails) == { // second part of missing check is to see what is missing! // look at the offical list of episodes, and look to see if we have any gaps DateTime today = DateTime.Now; TheTVDB.Instance.GetLock("UpToDateCheck"); foreach (ProcessedEpisode dbep in eps) { if ((dbep.EpNum > maxEpNumFound) || (localEps[dbep.EpNum] == null)) // not here locally { 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 bool noAirdatesUntilNow = true; // for specials "season", see if any season has any airdates // otherwise, check only up to the season we are considering for (int i = 1; i <= ((snum == 0) ? lastSeason : snum); i++) { if (this.HasAnyAirdates(si, i)) { noAirdatesUntilNow = false; break; } } // only add to the missing list if, either: // - force check is on // - there are no airdates at all, for up to and including this season // - there is an airdate, and it isn't in the future if (noAirdatesUntilNow || ((si.ForceCheckFuture || notFuture) && dtOK) || (si.ForceCheckNoAirdate && !dtOK)) { // then add it as officially missing this.TheActionList.Add(new ItemMissing(dbep, folder + System.IO.Path.DirectorySeparatorChar + TVSettings.Instance.FilenameFriendly(TVSettings.Instance.NamingStyle.NameForExt(dbep, null, folder.Length)))); } } else { // the file is here if (showList == null) this.mStats.NS_NumberOfEpisodes++; // do NFO and thumbnail checks if required FileInfo filo = localEps[dbep.EpNum]; // filename (or future filename) of the file this.TheActionList.Add(DownloadIdentifiers.ProcessEpisode(dbep, filo)); } } // up to date check, for each episode in thetvdb TheTVDB.Instance.Unlock("UpToDateCheck"); } // if doing missing check } // for each folder for this season of this show } // for each season of this show } // for each show this.UnlockShowItems(); this.RemoveIgnored(); }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { // get list of files being downloaded by uTorrent string resDatFile = TVSettings.Instance.ResumeDatPath; if (string.IsNullOrEmpty(resDatFile) || !File.Exists(resDatFile)) { return; } BTResume btr = new BTResume(prog, resDatFile); if (!btr.LoadResumeDat()) { return; } List <TorrentEntry> downloading = btr.AllFilesBeingDownloaded(); ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = this.ActionList.Count + 2; int n = 1; prog.Invoke(startpct); foreach (Item action1 in this.ActionList) { if (this.ActionCancel) { return; } prog.Invoke(startpct + (totPct - startpct) * (++n) / (c)); if (!(action1 is ItemMissing action)) { continue; } foreach (TorrentEntry te in downloading) { FileInfo file = new FileInfo(te.DownloadingTo); if (!TVSettings.Instance.UsefulExtension(file.Extension, false)) // not a usefile file extension { continue; } //do any of the possible names for the series match the filename? bool matched = (action.Episode.SI.getSimplifiedPossibleShowNames().Any(name => FileHelper.SimplifyAndCheckFilename(file.FullName, name))); if (!matched) { 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)) { toRemove.Add(action1); newList.Add(new ItemuTorrenting(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 override void Check(SetProgressDelegate prog, int startpct, int totPct) { prog.Invoke(0); ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int fileCount = 0; foreach (string s in this.mDoc.SearchFolders) { fileCount += DirCache.CountFiles(s, true); } int c = 0; DirCache dirCache = new DirCache(); foreach (String s in this.mDoc.SearchFolders) { if (this.ActionCancel) { return; } c = dirCache.AddFolder(prog, c, fileCount, s, true); } c = 0; int totalN = this.TheActionList.Count; foreach (Item action1 in this.TheActionList) { if (this.ActionCancel) { return; } prog.Invoke(50 + 50 * (++c) / (totalN + 1)); // second 50% of progress bar if (action1 is ItemMissing) { if (this.FindMissingEp(dirCache, (ItemMissing)(action1), newList, ActionCopyMoveRename.Op.Copy)) { toRemove.Add(action1); } } } if (TVSettings.Instance.KeepTogether) { this.KeepTogether(newList); } prog.Invoke(100); if (!TVSettings.Instance.LeaveOriginals) { // go through and change last of each operation on a given source file to a 'Move' // ideally do that move within same filesystem // sort based on source file, and destination drive, putting last if destdrive == sourcedrive newList.Sort(new ActionItemSorter()); // sort puts all the CopyMoveRenames together // then set the last of each source file to be a move for (int i = 0; i < newList.Count; i++) { ActionCopyMoveRename cmr1 = newList[i] as ActionCopyMoveRename; bool ok1 = cmr1 != null; if (!ok1) { continue; } bool last = i == (newList.Count - 1); ActionCopyMoveRename cmr2 = !last ? newList[i + 1] as ActionCopyMoveRename : null; bool ok2 = cmr2 != null; if (ok2) { ActionCopyMoveRename a1 = cmr1; ActionCopyMoveRename a2 = cmr2; if (!FileHelper.Same(a1.From, a2.From)) { a1.Operation = ActionCopyMoveRename.Op.Move; } } else { // last item, or last copymoverename item in the list ActionCopyMoveRename a1 = cmr1; a1.Operation = ActionCopyMoveRename.Op.Move; } } } foreach (Item i in toRemove) { this.TheActionList.Remove(i); } foreach (Item i in newList) { this.TheActionList.Add(i); } // if (Settings->ExportFOXML) // ExportFOXML(Settings->ExportFOXMLTo); }
public void CheckAgainstuTorrent(SetProgressDelegate prog, int startpct, int totPct) { // get list of files being downloaded by uTorrent string resDatFile = this.Settings.ResumeDatPath; if (string.IsNullOrEmpty(resDatFile) || !File.Exists(resDatFile)) return; BTResume btr = new BTResume(prog, resDatFile); if (!btr.LoadResumeDat(Args)) return; List<TorrentEntry> downloading = btr.AllFilesBeingDownloaded(this.Settings, Args); ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = this.TheActionList.Count + 2; int n = 1; prog.Invoke(startpct + totPct * n / c); foreach (Item Action1 in this.TheActionList) { if (this.ActionCancel) return; n++; prog.Invoke(100 * n / c); if (!(Action1 is ItemMissing)) continue; ItemMissing Action = (ItemMissing) (Action1); string showname = Helpers.SimplifyName(Action.Episode.SI.ShowName); foreach (TorrentEntry te in downloading) { FileInfo file = new FileInfo(te.DownloadingTo); if (!this.Settings.UsefulExtension(file.Extension, false)) // not a usefile file extension continue; if (this.SimplifyAndCheckFilename(file.FullName, showname, true, false)) // if (Regex::Match(simplifiedfname,"\\b"+showname+"\\b",RegexOptions::IgnoreCase)->Success) { int seasF; int epF; if (this.FindSeasEp(file, out seasF, out epF, Action.Episode.SI) && (seasF == Action.Episode.SeasonNumber) && (epF == Action.Episode.EpNum)) { toRemove.Add(Action1); newList.Add(new ItemuTorrenting(te, Action.Episode, Action.TheFileNoExt)); break; } } } } foreach (Item i in toRemove) this.TheActionList.Remove(i); foreach (Item Action in newList) this.TheActionList.Add(Action); prog.Invoke(startpct + totPct); }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { int c = ActionList.Count + 2; int n = 1; prog.Invoke(startpct); ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); try { foreach (ItemMissing action in ActionList.MissingItems()) { if (ActionCancel) { return; } prog.Invoke(startpct + ((totPct - startpct) * (++n) / (c))); ProcessedEpisode pe = action.Episode; string simpleShowName = Helpers.SimplifyName(action.Episode.Show.ShowName); string simpleSeriesName = Helpers.SimplifyName(action.Episode.TheSeries.Name); string imdbId = action.Episode.TheSeries.GetImdbNumber(); if (string.IsNullOrWhiteSpace(imdbId)) { continue; } WebClient client = new WebClient(); client.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); string response = client.DownloadString($"{TVSettings.Instance.SearchJSONURL}{imdbId}"); JObject jsonResponse = JObject.Parse(response); if (jsonResponse.ContainsKey(TVSettings.Instance.SearchJSONRootNode)) { foreach (JToken item in jsonResponse[TVSettings.Instance.SearchJSONRootNode]) { if (item != null && item is JObject episodeResponse) { if (episodeResponse.ContainsKey(TVSettings.Instance.SearchJSONFilenameToken) && episodeResponse.ContainsKey(TVSettings.Instance.SearchJSONURLToken)) { string itemName = (string)item[TVSettings.Instance.SearchJSONFilenameToken]; string itemUrl = (string)item[TVSettings.Instance.SearchJSONURLToken]; if (TVSettings.Instance.DetailedRSSJSONLogging) { LOGGER.Info("Processing JSON Item"); LOGGER.Info(episodeResponse.ToString); LOGGER.Info("Extracted"); LOGGER.Info($"Name: {itemName}"); LOGGER.Info($"URL: {itemUrl}"); } if (!FileHelper.SimplifyAndCheckFilename(itemName, simpleShowName, true, false) && !FileHelper.SimplifyAndCheckFilename(itemName, simpleSeriesName, true, false)) { continue; } if (!TVDoc.FindSeasEp(itemName, out int seas, out int ep, out int _, action.Episode.Show)) { continue; } if (TVSettings.Instance.DetailedRSSJSONLogging) { LOGGER.Info($"Season: {seas}"); LOGGER.Info($"Episode: {ep}"); } if (seas != pe.AppropriateSeasonNumber) { continue; } if (ep != pe.AppropriateEpNum) { continue; } LOGGER.Info( $"Adding {itemUrl} as it appears to be match for {pe.Show.ShowName} S{pe.AppropriateSeasonNumber}E{pe.AppropriateEpNum}"); newItems.Add(new ActionTDownload(itemName, itemUrl, action.TheFileNoExt, pe)); toRemove.Add(action); } else { LOGGER.Info( $"{TVSettings.Instance.SearchJSONFilenameToken} or {TVSettings.Instance.SearchJSONURLToken} not found in {TVSettings.Instance.SearchJSONURL}{imdbId} for {action.Episode.TheSeries.Name}"); } } } } else { LOGGER.Info( $"{TVSettings.Instance.SearchJSONRootNode} not found in {TVSettings.Instance.SearchJSONURL}{imdbId} for {action.Episode.TheSeries.Name}"); } } } catch (WebException ex) { LOGGER.Info(ex, $"Failed to Access {TVSettings.Instance.SearchJSONURL}"); } foreach (ActionTDownload x in FindDuplicates(newItems)) { newItems.Remove(x); } foreach (Item i in toRemove) { ActionList.Remove(i); } foreach (Item action in newItems) { ActionList.Add(action); } prog.Invoke(totPct); }
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); }
protected void Prog(int percent, string message) => SetProg?.Invoke(percent, message);
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { prog.Invoke(startpct); ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int fileCount = 0; foreach (string s in TVSettings.Instance.DownloadFolders) { fileCount += DirCache.CountFiles(s, true); } DirCache dirCache = new DirCache(); foreach (string s in TVSettings.Instance.DownloadFolders) { if (ActionCancel) { return; } dirCache.AddFolder(prog, 0, fileCount, s, true); } int currentItem = 0; int totalN = ActionList.Count; foreach (ItemMissing me in ActionList.MissingItems()) { if (ActionCancel) { return; } prog.Invoke(startpct + ((totPct - startpct) * (++currentItem) / (totalN + 1))); ItemList thisRound = new ItemList(); List <DirCacheEntry> matchedFiles = new List <DirCacheEntry>(); foreach (DirCacheEntry dce in dirCache) { if (!ReviewFile(me, thisRound, dce)) { continue; } matchedFiles.Add(dce); } if (matchedFiles.Count == 1) { if (!OtherActionsMatch(matchedFiles[0], me)) { toRemove.Add(me); newList.AddRange(thisRound); } else { LOGGER.Warn($"Ignoring potential match for {me.Episode.Show.ShowName} S{me.Episode.AppropriateSeasonNumber} E{me.Episode.AppropriateEpNum}: with file {matchedFiles[0]?.TheFile.FullName} as there are multiple actions for that file"); me.AddComment( $"Ignoring potential match with file {matchedFiles[0]?.TheFile.FullName} as there are multiple actions for that file"); } } else if (matchedFiles.Count > 1) { List <DirCacheEntry> bestMatchedFiles = IdentifyBestMatches(matchedFiles); if (bestMatchedFiles.Count == 1) { //We have one file that is better, lets use it toRemove.Add(me); newList.AddRange(thisRound); } else { foreach (DirCacheEntry matchedFile in matchedFiles) { LOGGER.Warn( $"Ignoring potential match for {me.Episode.Show.ShowName} S{me.Episode.AppropriateSeasonNumber} E{me.Episode.AppropriateEpNum}: with file {matchedFile?.TheFile.FullName} as there are multiple files for that action"); me.AddComment( $"Ignoring potential match with file {matchedFile?.TheFile.FullName} as there are multiple files for that action"); } } } } if (TVSettings.Instance.KeepTogether) { KeepTogether(newList); } prog.Invoke(totPct); if (!TVSettings.Instance.LeaveOriginals) { // go through and change last of each operation on a given source file to a 'Move' // ideally do that move within same filesystem // sort based on source file, and destination drive, putting last if destdrive == sourcedrive newList.Sort(new ActionItemSorter()); // sort puts all the CopyMoveRenames together // then set the last of each source file to be a move for (int i = 0; i < newList.Count; i++) { ActionCopyMoveRename cmr1 = newList[i] as ActionCopyMoveRename; bool ok1 = cmr1 != null; if (!ok1) { continue; } bool last = i == (newList.Count - 1); ActionCopyMoveRename cmr2 = !last ? newList[i + 1] as ActionCopyMoveRename : null; bool ok2 = cmr2 != null; if (ok2) { ActionCopyMoveRename a1 = cmr1; ActionCopyMoveRename a2 = cmr2; if (!FileHelper.Same(a1.From, a2.From)) { a1.Operation = ActionCopyMoveRename.Op.move; } } else { // last item, or last copymoverename item in the list ActionCopyMoveRename a1 = cmr1; a1.Operation = ActionCopyMoveRename.Op.move; } } } foreach (Item i in toRemove) { ActionList.Remove(i); } foreach (Item i in newList) { ActionList.Add(i); } }
public override void Check(SetProgressDelegate prog, int startpct, int totPct) { int c = ActionList.Count + 2; int n = 1; prog.Invoke(startpct); // ReSharper disable once InconsistentNaming RssItemList RSSList = new RssItemList(); foreach (string s in TVSettings.Instance.RSSURLs) { RSSList.DownloadRSS(s, TVSettings.Instance.FNPRegexs); } ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); foreach (ItemMissing action in ActionList.MissingItems()) { if (ActionCancel) { return; } prog.Invoke(startpct + ((totPct - startpct) * (++n) / (c))); ProcessedEpisode pe = action.Episode; string simpleShowName = Helpers.SimplifyName(pe.Show.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheSeries.Name); foreach (RSSItem rss in RSSList) { if ( !FileHelper.SimplifyAndCheckFilename(rss.ShowName, simpleShowName, true, false) && !( string.IsNullOrEmpty(rss.ShowName) && FileHelper.SimplifyAndCheckFilename(rss.Title, simpleSeriesName, true, false) ) ) { continue; } if (rss.Season != pe.AppropriateSeasonNumber) { continue; } if (rss.Episode != pe.AppropriateEpNum) { continue; } LOGGER.Info($"Adding {rss.URL} as it appears to be match for {action.Episode.Show.ShowName} S{action.Episode.AppropriateSeasonNumber}E{action.Episode.AppropriateEpNum}"); newItems.Add(new ActionTDownload(rss, action.TheFileNoExt, pe)); toRemove.Add(action); } } foreach (ActionTDownload x in FindDuplicates(newItems)) { newItems.Remove(x); } foreach (Item i in toRemove) { ActionList.Remove(i); } foreach (Item action in newItems) { ActionList.Add(action); } prog.Invoke(totPct); }