Beispiel #1
0
        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);
        }
Beispiel #2
0
        private static QueueSlotsSlot CreateQueueSlotsSlot([NotNull] XElement slot, string simpleShowName, ItemMissing action)
        {
            string filename = slot.Attribute("filename")?.Value;

            if (string.IsNullOrWhiteSpace(filename))
            {
                return(null);
            }

            FileInfo file = new FileInfo(filename);

            if (!FileHelper.SimplifyAndCheckFilename(file.FullName, simpleShowName, true, false))
            {
                return(null);
            }

            if (!FinderHelper.FindSeasEp(file, out int seasF, out int epF, out int _,
                                         action.Episode.Show) ||
                (seasF != action.Episode.AppropriateSeasonNumber) ||
                (epF != action.Episode.AppropriateEpNum))
            {
                return(null);
            }

            return(new QueueSlotsSlot
            {
                Filename = filename,
                Mb = slot.Attribute("mb")?.Value,
                Sizeleft = slot.Attribute("sizeleft")?.Value,
                Status = slot.Attribute("status")?.Value,
                Timeleft = slot.Attribute("timeleft")?.Value
            });
        }
Beispiel #3
0
        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 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);
        }
Beispiel #5
0
 public bool NameMatchInitial(string text)
 {
     return(GetSimplifiedPossibleShowNames().Any(name => FileHelper.SimplifyAndCheckFilename(text, name)));
 }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        // 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)
        {
            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 ?

            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;
                    }

                    //do any of the possible names for the series match the filename?
                    matched = (me.Episode.SI.getSimplifiedPossibleShowNames().Any(name => FileHelper.SimplifyAndCheckFilename(dce.SimplifiedFullName, name)));

                    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;
                    logger.Warn(e, "Path too long. " + dce.TheFile.FullName);

                    t += ".  More information is available in the log file";
                    if ((!this.mDoc.Args.Unattended) && (!this.mDoc.Args.Hide))
                    {
                        MessageBox.Show(t, "Path too long", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }

                    t  = "DirectoryName " + dce.TheFile.DirectoryName + ", File name: " + dce.TheFile.Name;
                    t += matched ? ", matched.  " : ", no match.  ";
                    if (matched)
                    {
                        t += "Show: " + me.Episode.TheSeries.Name + ", Season " + season + ", Ep " + epnum + ".  ";
                        t += "To: " + me.TheFileNoExt;
                    }
                    logger.Warn(t);
                }
            }

            return(false);
        }
        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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        private bool ReviewFile(ItemMissing me, ItemList addTo, DirCacheEntry dce)
        {
            if (ActionCancel)
            {
                return(true);
            }

            int  season  = me.Episode.AppropriateSeasonNumber;
            int  epnum   = me.Episode.AppropriateEpNum;
            bool matched = false;

            try
            {
                if (FileHelper.IgnoreFile(dce.TheFile))
                {
                    return(false);
                }

                //do any of the possible names for the series match the filename?
                matched = (me.Episode.Show.GetSimplifiedPossibleShowNames()
                           .Any(name => FileHelper.SimplifyAndCheckFilename(dce.SimplifiedFullName, name)));

                if (matched)
                {
                    bool regularMatch = TVDoc.FindSeasEp(dce.TheFile, out int seasF, out int epF, out int maxEp, me.Episode.Show) &&
                                        seasF == season &&
                                        epF == epnum;

                    bool sequentialMatch = me.Episode.Show.UseSequentialMatch &&
                                           TVDoc.MatchesSequentialNumber(dce.TheFile.Name, ref seasF, ref epF, me.Episode) &&
                                           seasF == season &&
                                           epF == epnum;

                    if (regularMatch || sequentialMatch)
                    {
                        if (maxEp != -1 && TVSettings.Instance.AutoMergeDownloadEpisodes)
                        {
                            ShowRule sr = new ShowRule
                            {
                                DoWhatNow = RuleAction.kMerge,
                                First     = epF,
                                Second    = maxEp
                            };
                            me.Episode.Show?.AddSeasonRule(seasF, sr);

                            LOGGER.Info(
                                $"Looking at {me.Episode.Show.ShowName} and have identified that episode {epF} and {maxEp} of season {seasF} have been merged into one file {dce.TheFile.FullName}");
                            LOGGER.Info($"Added new rule automatically for {sr}");

                            //Regenerate the episodes with the new rule added
                            ShowLibrary.GenerateEpisodeDict(me.Episode.Show);

                            //Get the newly created processed episode we are after
                            // ReSharper disable once InconsistentNaming
                            ProcessedEpisode newPE = me.Episode;
                            foreach (ProcessedEpisode pe in me.Episode.Show.SeasonEpisodes[seasF])
                            {
                                if (pe.AppropriateEpNum == epF && pe.EpNum2 == maxEp)
                                {
                                    newPE = pe;
                                }
                            }

                            me = new ItemMissing(newPE, me.TargetFolder,
                                                 TVSettings.Instance.FilenameFriendly(TVSettings.Instance.NamingStyle.NameFor(newPE)));
                        }
                        FileInfo fi = new FileInfo(me.TheFileNoExt + dce.TheFile.Extension);

                        if (TVSettings.Instance.PreventMove)
                        {
                            //We do not want to move the file, just rename it
                            fi = new FileInfo(dce.TheFile.DirectoryName + System.IO.Path.DirectorySeparatorChar + me.Filename +
                                              dce.TheFile.Extension);
                        }

                        // don't remove the base search folders
                        bool doTidyup = true;
                        foreach (string folder in TVSettings.Instance.DownloadFolders)
                        {
                            if (folder.SameDirectoryLocation(fi.Directory.FullName))
                            {
                                doTidyup = false;
                                break;
                            }
                        }

                        if (dce.TheFile.FullName != fi.FullName)
                        {
                            addTo.Add(new ActionCopyMoveRename(ActionCopyMoveRename.Op.copy, dce.TheFile, fi, me.Episode,
                                                               doTidyup ? TVSettings.Instance.Tidyup : null, me));
                        }

                        DownloadIdentifiersController di = new DownloadIdentifiersController();

                        // if we're copying/moving a file across, we might also want to make a thumbnail or NFO for it
                        addTo.Add(di.ProcessEpisode(me.Episode, fi));

                        return(true);
                    }
                }
            }
            catch (System.IO.PathTooLongException e)
            {
                string t = "Path too long. " + dce.TheFile.FullName + ", " + e.Message;
                LOGGER.Warn(e, "Path too long. " + dce.TheFile.FullName);

                t += ".  More information is available in the log file";
                if ((!Doc.Args.Unattended) && (!Doc.Args.Hide))
                {
                    MessageBox.Show(t, "Path too long", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }

                t  = "DirectoryName " + dce.TheFile.DirectoryName + ", File name: " + dce.TheFile.Name;
                t += matched ? ", matched.  " : ", no match.  ";
                if (matched)
                {
                    t += "Show: " + me.Episode.TheSeries.Name + ", Season " + season + ", Ep " + epnum + ".  ";
                    t += "To: " + me.TheFileNoExt;
                }
                LOGGER.Warn(t);
            }
            return(false);
        }
Beispiel #18
0
        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);
        }