protected static bool RssMatch([NotNull] RSSItem rss, [NotNull] ProcessedEpisode pe) { string simpleShowName = Helpers.SimplifyName(pe.Show.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheCachedSeries.Name); if (!FileHelper.SimplifyAndCheckFilename(rss.ShowName, simpleShowName, true, false) && !( string.IsNullOrEmpty(rss.ShowName) && FileHelper.SimplifyAndCheckFilename(rss.Title, simpleSeriesName, true, false) ) ) { return(false); } if (rss.Season != pe.AppropriateSeasonNumber) { return(false); } if (rss.Episode != pe.AppropriateEpNum) { return(false); } return(true); }
public List <string> GetSimplifiedPossibleShowNames() { List <string> possibles = new List <string>(); string simplifiedShowName = Helpers.SimplifyName(ShowName); if (simplifiedShowName != "") { possibles.Add(simplifiedShowName); } //Check the custom show name too if (UseCustomShowName) { string simplifiedCustomShowName = Helpers.SimplifyName(CustomShowName); if (simplifiedCustomShowName != "") { possibles.Add(simplifiedCustomShowName); } } //Also add the aliases provided possibles.AddRange(from alias in AliasNames select Helpers.SimplifyName(alias)); return(possibles); }
private IEnumerable <string> GetSimplifiedPossibleShowNames() { List <string> possibles = new List <string>(); string simplifiedShowName = Helpers.SimplifyName(ShowName); if (simplifiedShowName != "") { possibles.Add(simplifiedShowName); } //Check the custom show name too if (UseCustomShowName) { string simplifiedCustomShowName = Helpers.SimplifyName(CustomShowName); if (simplifiedCustomShowName != "") { possibles.Add(simplifiedCustomShowName); } } //Also add the aliases provided possibles.AddNullableRange(AliasNames.Select(Helpers.SimplifyName)); //Also use the aliases from theTVDB possibles.AddNullableRange(TheSeries()?.Aliases()?.Select(Helpers.SimplifyName)); return(possibles); }
public List <String> getSimplifiedPossibleShowNames() { List <String> possibles = new List <String>(); String simplifiedShowName = Helpers.SimplifyName(this.ShowName); if (!(simplifiedShowName == "")) { possibles.Add(simplifiedShowName); } //Check the custom show name too if (this.UseCustomShowName) { String simplifiedCustomShowName = Helpers.SimplifyName(this.CustomShowName); if (!(simplifiedCustomShowName == "")) { possibles.Add(simplifiedCustomShowName); } } //Also add the aliases provided possibles.AddRange(from alias in this.AliasNames select Helpers.SimplifyName(alias)); return(possibles); }
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); }
public static int SimplifyAndCheckFilenameLength(string filename, string showName, bool simplifyfilename, bool simplifyshowname) { Match match = Regex.Match(simplifyfilename ? Helpers.SimplifyName(filename) : filename, "\\b" + (simplifyshowname ? Helpers.SimplifyName(showName) : showName) + "\\b", RegexOptions.IgnoreCase); if (match.Success) { return(match.Length); } return(0); }
private static string NormalJackettUrl(ProcessedEpisode processedEpisode) { string serverName = TVSettings.Instance.JackettServer; string serverPort = TVSettings.Instance.JackettPort; string allIndexer = TVSettings.Instance.JackettIndexer; string apikey = TVSettings.Instance.JackettAPIKey; string?simpleShowName = WebUtility.UrlEncode(Helpers.SimplifyName(processedEpisode.Show.ShowName)); return ($"http://{serverName}:{serverPort}{allIndexer}/api?t=tvsearch&q={simpleShowName}&tvdbid={processedEpisode.Show.TvdbCode}&season={processedEpisode.AppropriateSeasonNumber}&ep={processedEpisode.AppropriateEpNum}&apikey={apikey}"); }
protected override void DoCheck(SetProgressDelegate prog, ICollection <ShowItem> showList, TVDoc.ScanSettings settings) { if (string.IsNullOrEmpty(TVSettings.Instance.SABAPIKey) || string.IsNullOrEmpty(TVSettings.Instance.SABHostPort)) { LOGGER.Info("Searching SABnzxdb Feeds is cancelled as the key and host/port are notprovided in Preferences."); return; } // get list of files being downloaded by SABnzbd XElement x = GetSabDownload(TVSettings.Instance.SABAPIKey, TVSettings.Instance.SABHostPort); if (x is null) { return; } ItemList newList = new ItemList(); ItemList toRemove = new ItemList(); int c = ActionList.MissingItems().Count() + 1; int n = 0; foreach (ItemMissing action in ActionList.MissingItems().ToList()) { if (settings.Token.IsCancellationRequested) { return; } UpdateStatus(n++, c, action.Filename); if (action.Episode?.Show is null) { continue; } string simpleShowName = Helpers.SimplifyName(action.Episode.Show.ShowName); if (string.IsNullOrWhiteSpace(simpleShowName)) { continue; } foreach (QueueSlotsSlot te in x.Descendants("slots").Select(slot => CreateQueueSlotsSlot(slot, simpleShowName, action)).Where(te => !(te is null))) { toRemove.Add(action); newList.Add(new ItemDownloading(te, action.Episode, action.TheFileNoExt, DownloadApp.SABnzbd)); break; } } ActionList.Replace(toRemove, newList); }
public DirCacheEntry(FileInfo f) { this.TheFile = f; this.SimplifiedFullName = Helpers.SimplifyName(f.FullName); this.LowerName = f.Name.ToLower(); this.Length = f.Length; if (TVSettings.Instance == null) return; this.HasUsefulExtension_NotOthersToo = TVSettings.Instance.UsefulExtension(f.Extension, false); this.HasUsefulExtension_OthersToo = this.HasUsefulExtension_NotOthersToo | TVSettings.Instance.UsefulExtension(f.Extension, true); }
// see if showname is somewhere in filename public static bool SimplifyAndCheckFilename(string filename, string showname, bool simplifyfilename, bool simplifyshowname) { return(Regex.Match(simplifyfilename ? Helpers.SimplifyName(filename) : filename, "\\b" + (simplifyshowname ? Helpers.SimplifyName(showname) : showname) + "\\b", RegexOptions.IgnoreCase).Success); }
public bool NameMatchFilters(string text) { return(GetSimplifiedPossibleShowNames().Any(name => name.Contains(Helpers.SimplifyName(text), StringComparison.OrdinalIgnoreCase))); }
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); }
protected static bool RssMatch([NotNull] RSSItem rss, [NotNull] MovieConfiguration pe) { string simpleShowName = Helpers.SimplifyName(pe.ShowName); return(FileHelper.SimplifyAndCheckFilename(rss.ShowName.HasValue()? rss.ShowName: rss.Title, simpleShowName, true, false)); }
public DirCacheEntry(FileInfo f) { this.TheFile = f; this.SimplifiedFullName = Helpers.SimplifyName(f.FullName); this.Length = f.Length; }
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); }
protected override void DoCheck(SetProgressDelegate prog, ICollection <ShowItem> showList, TVDoc.ScanSettings settings) { if (TVSettings.Instance.SearchRSSManualScanOnly && settings.Unattended) { LOGGER.Info("Searching RSS Feeds is cancelled as this is an unattended scan"); return; } int c = ActionList.MissingItems().Count() + 2; int n = 1; UpdateStatus(n, c, "Searching on RSS Feed..."); // ReSharper disable once InconsistentNaming RssItemList RSSList = new RssItemList(); foreach (string s in TVSettings.Instance.RSSURLs) { RSSList.DownloadRSS(s, TVSettings.Instance.FNPRegexs, TVSettings.Instance.RSSUseCloudflare); } ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); foreach (ItemMissing action in ActionList.MissingItems().ToList()) { if (settings.Token.IsCancellationRequested) { return; } UpdateStatus(n++, c, action.Filename); ProcessedEpisode pe = action.Episode; string simpleShowName = Helpers.SimplifyName(pe.Show.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheSeries.Name); ItemList newItemsForThisMissingEpisode = new ItemList(); 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} from RSS feed as it appears to be match for {action.Episode.Show.ShowName} S{action.Episode.AppropriateSeasonNumber}E{action.Episode.AppropriateEpNum}"); newItemsForThisMissingEpisode.Add(new ActionTDownload(rss, action.TheFileNoExt, pe, action)); toRemove.Add(action); } foreach (ActionTDownload x in FindDuplicates(newItemsForThisMissingEpisode)) { newItemsForThisMissingEpisode.Remove(x); } newItems.AddNullableRange(newItemsForThisMissingEpisode); } ActionList.Replace(toRemove, newItems); }
public DirCacheEntry([NotNull] FileInfo f) { TheFile = f; SimplifiedFullName = Helpers.SimplifyName(f.FullName); Length = f.Length; }
private static bool SimplifyAndCheckFilenameAtStart(string filename, string showName, bool simplifyFilename, bool simplifyShowName) { string showPattern = simplifyShowName ? Helpers.SimplifyName(showName) : showName; return((simplifyFilename ? Helpers.SimplifyName(filename) : filename).StartsWith(showPattern, StringComparison.CurrentCultureIgnoreCase)); }
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 FileInfo MatchMissing(string torrentFile, int torrentFileNum, string nameInTorrent) { // returns true if we found a match (if actSetPrio is on, true also means we have set a priority for this file) string simplifiedfname = Helpers.SimplifyName(nameInTorrent); foreach (Item action1 in MissingList) { if ((!(action1 is ItemMissing)) && (!(action1 is ItemDownloading))) { continue; } ProcessedEpisode m = action1.Episode; string name = null; switch (action1) { case ItemMissing action: name = action.TheFileNoExt; break; case ItemDownloading actionIp: name = actionIp.DesiredLocationNoExt; break; default: throw new ArgumentOutOfRangeException(); } if ((m is null) || string.IsNullOrEmpty(name)) { continue; } // see if the show name matches... if (FileHelper.SimplifyAndCheckFilename(simplifiedfname, m.TheCachedSeries.Name, false, true)) { // see if season and episode match bool findFile = FinderHelper.FindSeasEp("", simplifiedfname, out int seasF, out int epF, out int maxEp, m.Show, Rexps, out TVSettings.FilenameProcessorRE rex); if (findFile && (seasF == m.AppropriateSeasonNumber) && (epF == m.AppropriateEpNum)) { // match! // get extension from nameInTorrent int p = nameInTorrent.LastIndexOf(".", StringComparison.Ordinal); string ext = (p == -1) ? "" : nameInTorrent.Substring(p); AlterResume(torrentFile, torrentFileNum, name + ext); if (SetPrios) { SetResumePrio(torrentFile, torrentFileNum, BTPrio.Normal); } return(new FileInfo(name + ext)); } } } return(null); }
// consider each of the files, see if it is suitable for series "ser" and episode "epi" // if so, add a rcitem for copy to "fi" public bool FindMissingEp(DirCache dirCache, ItemMissing me, ItemList addTo, ActionCopyMoveRename.Op whichOp) { string showname = me.Episode.SI.ShowName; int season = me.Episode.SeasonNumber; //String ^toName = FilenameFriendly(Settings->NamingStyle->NameFor(me->PE)); int epnum = me.Episode.EpNum; // TODO: find a 'best match', or use first ? showname = Helpers.SimplifyName(showname); foreach (DirCacheEntry dce in dirCache) { if (this.ActionCancel) { return(true); } bool matched = false; try { if (!dce.HasUsefulExtension_NotOthersToo) // not a usefile file extension { continue; } if (TVSettings.Instance.IgnoreSamples && dce.LowerName.Contains("sample") && ((dce.Length / (1024 * 1024)) < TVSettings.Instance.SampleFileMaxSizeMB)) { continue; } matched = Regex.Match(dce.SimplifiedFullName, "\\b" + showname + "\\b", RegexOptions.IgnoreCase).Success; // if we don't match the main name, then test the aliases if (!matched) { foreach (string alias in me.Episode.SI.AliasNames) { string aliasName = Helpers.SimplifyName(alias); matched = Regex.Match(dce.SimplifiedFullName, "\\b" + aliasName + "\\b", RegexOptions.IgnoreCase).Success; if (matched) { break; } } } if (matched) { int seasF; int epF; if ((TVDoc.FindSeasEp(dce.TheFile, out seasF, out epF, me.Episode.SI) && (seasF == season) && (epF == epnum)) || (me.Episode.SI.UseSequentialMatch && TVDoc.MatchesSequentialNumber(dce.TheFile.Name, ref seasF, ref epF, me.Episode) && (seasF == season) && (epF == epnum))) { FileInfo fi = new FileInfo(me.TheFileNoExt + dce.TheFile.Extension); // don't remove the base search folders bool doTidyup = true; foreach (String folder in this.mDoc.SearchFolders) { // http://stackoverflow.com/questions/1794025/how-to-check-whether-2-directoryinfo-objects-are-pointing-to-the-same-directory if (String.Compare(folder.ToLower().TrimEnd('\\'), fi.Directory.FullName.ToLower().TrimEnd('\\'), StringComparison.InvariantCultureIgnoreCase) == 0) { doTidyup = false; break; } } addTo.Add(new ActionCopyMoveRename(whichOp, dce.TheFile, fi, me.Episode, doTidyup ? TVSettings.Instance.Tidyup : null)); 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; t += ". Try to display more info?"; DialogResult dr = MessageBox.Show(t, "Path too long", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (dr == DialogResult.Yes) { 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; } MessageBox.Show(t, "Path too long", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } return(false); }
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); }
private static void FindMissingEpisode([NotNull] ItemMissing action, ItemList toRemove, ItemList newItems, UrlCache cache) { ProcessedEpisode pe = action.Episode; string imdbId = pe.TheSeries.GetImdbNumber(); if (string.IsNullOrWhiteSpace(imdbId)) { return; } string simpleShowName = Helpers.SimplifyName(pe.Show.ShowName); string simpleSeriesName = Helpers.SimplifyName(pe.TheSeries.Name); ItemList newItemsForThisMissingEpisode = new ItemList(); string response = cache.GetUrl($"{TVSettings.Instance.SearchJSONURL}{imdbId}", TVSettings.Instance.SearchJSONUseCloudflare); if (string.IsNullOrWhiteSpace(response)) { LOGGER.Warn( $"Got no response from {TVSettings.Instance.SearchJSONURL}{imdbId} for {action.Episode.TheSeries.Name}"); return; } JObject jsonResponse = JObject.Parse(response); if (jsonResponse.ContainsKey(TVSettings.Instance.SearchJSONRootNode)) { foreach (JToken item in jsonResponse[TVSettings.Instance.SearchJSONRootNode]) { if (item is null || !(item is JObject episodeResponse)) { continue; } 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]; long itemSizeBytes = CalculateItemSizeBytes(item); if (TVSettings.Instance.DetailedRSSJSONLogging) { LOGGER.Info("Processing JSON Item"); LOGGER.Info(episodeResponse.ToString); LOGGER.Info("Extracted"); LOGGER.Info($"Name: {itemName}"); LOGGER.Info($"URL: {itemUrl}"); LOGGER.Info($"Size: {itemSizeBytes}"); } if (!FileHelper.SimplifyAndCheckFilename(itemName, simpleShowName, true, false) && !FileHelper.SimplifyAndCheckFilename(itemName, simpleSeriesName, true, false)) { continue; } if (!FinderHelper.FindSeasEp(itemName, out int seas, out int ep, out int _, pe.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} from JSON page as it appears to be match for {pe.Show.ShowName} S{pe.AppropriateSeasonNumber}E{pe.AppropriateEpNum}"); newItemsForThisMissingEpisode.Add(new ActionTDownload(itemName, itemSizeBytes, itemUrl, action.TheFileNoExt, pe, action)); 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}"); } RemoveDuplicates(newItemsForThisMissingEpisode); newItems.AddNullableRange(newItemsForThisMissingEpisode); }
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 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); }