private static void FindMissingEpisode([NotNull] ShowItemMissing action, ItemList toRemove, ItemList newItems) { ProcessedEpisode processedEpisode = action.MissingEpisode; string url = TVSettings.Instance.UseJackettTextSearch ? TextJackettUrl(processedEpisode) : NormalJackettUrl(processedEpisode); RssItemList rssList = new RssItemList(); rssList.DownloadRSS(url, false, "Jackett"); ItemList newItemsForThisMissingEpisode = new ItemList(); foreach (RSSItem rss in rssList.Where(rss => RssMatch(rss, processedEpisode))) { if (TVSettings.Instance.DetailedRSSJSONLogging) { LOGGER.Info( $"Adding {rss.URL} from RSS feed as it appears to be match for {processedEpisode.Show.ShowName} S{processedEpisode.AppropriateSeasonNumber}E{processedEpisode.AppropriateEpNum}"); } ItemDownloading becomes = new ItemDownloading(new FutureTorrentEntry(rss.URL, action.TheFileNoExt), action.MissingEpisode, action.TheFileNoExt, DownloadingFinder.DownloadApp.qBitTorrent, action); newItemsForThisMissingEpisode.Add(new ActionTDownload(rss, action, becomes)); toRemove.Add(action); } foreach (ActionTDownload x in FindDuplicates(newItemsForThisMissingEpisode)) { newItemsForThisMissingEpisode.Remove(x); } newItems.AddNullableRange(newItemsForThisMissingEpisode); }
private static int TypeNumber(Item a) { return(a switch { ShowItemMissing _ => 1, MovieItemMissing _ => 2, ActionCopyMoveRename _ => 3, ActionMoveRenameDirectory _ => 4, ActionTDownload _ => 5, ActionDownloadImage _ => 6, ActionMede8erViewXML _ => 7, ActionMede8erXML _ => 8, ActionNfo _ => 9, ActionPyTivoMeta _ => 10, ActionWdtvMeta _ => 11, ItemDownloading _ => 12, ActionDeleteFile _ => 13, ActionDeleteDirectory _ => 14, ActionDateTouchEpisode _ => 15, ActionDateTouchSeason _ => 16, ActionDateTouchMedia _ => 17, ActionDateTouchMovie _ => 18, ActionTRemove _ => 19, _ => throw new NotSupportedException() });
protected override void DoCheck(SetProgressDelegate prog, 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.Missing.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.RSSUseCloudflare, "RSS"); } ItemList newItems = new ItemList(); ItemList toRemove = new ItemList(); foreach (ShowItemMissing action in ActionList.MissingEpisodes.ToList()) { if (settings.Token.IsCancellationRequested) { return; } UpdateStatus(n++, c, action.Filename); ProcessedEpisode pe = action.MissingEpisode; ItemList newItemsForThisMissingEpisode = new ItemList(); foreach (RSSItem rss in RSSList.Where(rss => RssMatch(rss, pe))) { LOGGER.Info( $"Adding {rss.URL} from RSS feed as it appears to be match for {pe.Show.ShowName} {pe}"); ItemDownloading eventualItem = new ItemDownloading(new FutureTorrentEntry(rss.URL, action.TheFileNoExt), action.MissingEpisode, action.TheFileNoExt, DownloadingFinder.DownloadApp.qBitTorrent, action); newItemsForThisMissingEpisode.Add(new ActionTDownload(rss, action, eventualItem)); toRemove.Add(action); } foreach (ActionTDownload x in FindDuplicates(newItemsForThisMissingEpisode)) { newItemsForThisMissingEpisode.Remove(x); } newItems.AddNullableRange(newItemsForThisMissingEpisode); } ActionList.Replace(toRemove, newItems); }
public ActionTDownload(string name, long sizeBytes, int seeders, string url, string toWhereNoExt, ProcessedEpisode?pe, ItemMissing me, string upstreamSource, ItemDownloading becomes) { Episode = pe; SourceName = name; this.url = url; theFileNoExt = toWhereNoExt; UpstreamSource = upstreamSource; UndoItemMissing = me; this.sizeBytes = sizeBytes; Seeders = seeders; this.becomes = becomes; }
public ActionTDownload([NotNull] RSSItem rss, ItemMissing me, ItemDownloading becomes) { SourceName = rss.Title; url = rss.URL; theFileNoExt = me.TheFileNoExt; UpstreamSource = rss.UpstreamSource; Episode = me.Episode; Movie = me.Movie; UndoItemMissing = me; Seeders = rss.Seeders; sizeBytes = rss.Bytes; UpstreamSource = rss.UpstreamSource; this.becomes = becomes; }
private static void FindMissingEpisode([NotNull] ShowItemMissing action, ItemList toRemove, ItemList newItems, UrlCache cache) { ProcessedEpisode pe = action.MissingEpisode; string imdbId = pe.TheCachedSeries.GetImdbNumber(); if (string.IsNullOrWhiteSpace(imdbId)) { return; } string simpleShowName = pe.Show.ShowName.CompareName(); string simpleSeriesName = pe.TheCachedSeries.Name.CompareName(); 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.MissingEpisode.TheCachedSeries.Name}"); return; } JObject jsonResponse = JObject.Parse(response); if (jsonResponse.ContainsKey(TVSettings.Instance.SearchJSONRootNode)) { JToken?x = jsonResponse[TVSettings.Instance.SearchJSONRootNode]; if (x is null) { LOGGER.Warn($"Could not find {TVSettings.Instance.SearchJSONRootNode} in JSON Repsonse {jsonResponse}"); return; } foreach (JToken item in x) { 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]; int seeders = (int)item[TVSettings.Instance.SearchJSONSeedersToken]; 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}"); LOGGER.Info($"Seeds: {seeders}"); } if (itemName is null || itemUrl is null) { continue; } 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}"); ItemDownloading becomes = new ItemDownloading(new FutureTorrentEntry(itemUrl, action.TheFileNoExt), action.MissingEpisode, action.TheFileNoExt, DownloadingFinder.DownloadApp.qBitTorrent, action); newItemsForThisMissingEpisode.Add(new ActionTDownload(itemName, itemSizeBytes, seeders, itemUrl, action.TheFileNoExt, pe, action, $"JSON WebPage: {TVSettings.Instance.SearchJSONURL}{imdbId}", becomes)); toRemove.Add(action); } else { LOGGER.Info( $"{TVSettings.Instance.SearchJSONFilenameToken} or {TVSettings.Instance.SearchJSONURLToken} not found in {TVSettings.Instance.SearchJSONURL}{imdbId} for {action.MissingEpisode.TheCachedSeries.Name}"); } } } else { LOGGER.Info( $"{TVSettings.Instance.SearchJSONRootNode} not found in {TVSettings.Instance.SearchJSONURL}{imdbId} for {action.MissingEpisode.TheCachedSeries.Name}"); } RemoveDuplicates(newItemsForThisMissingEpisode); newItems.AddNullableRange(newItemsForThisMissingEpisode); }