예제 #1
0
 public RssDownloaderTests()
 {
     _feedReader    = Substitute.For <IFeedReader>();
     _articleReader = Substitute.For <IArticleReader>();
     _repository    = Substitute.For <ISyndicationItemRepository>();
     _downloader    = new RssDownloader(_feedReader, _articleReader, _repository);
 }
예제 #2
0
        public void Get_files_to_download()
        {
            var contentMatcher = new ShowMatcher("Test 123");

            string[] downloadedLinks = { "rabble123", "rabble321" };

            var feed = new RssFeed();

            feed.Items = new List <RssItem>()
            {
                new RssItem()
                {
                    Link = "rabble444", Title = "Test 123 - S01E02.1080P"
                },
                new RssItem()
                {
                    Link = "rabble321", Title = "Test 123 - S01E03.1080P"
                }
            };

            var downloader = new RssDownloader(feed, "", "", contentMatcher);

            downloader.DownloadedLinks = downloadedLinks.ToList();

            var filesToDownload = downloader.UrlToDownload();

            Assert.AreEqual(1, filesToDownload.Count);
            Assert.IsTrue(filesToDownload.First() == "rabble444");
        }
예제 #3
0
        public FilterDynamicDataViewModel()
        {
            this.WhenActivated((CompositeDisposable disposables) =>
            {
                _searchResultSource = new SourceList <RssEntry>().DisposeWith(disposables);

                _searchResultSource
                .Connect()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out var searchResultsBinding)
                .Subscribe()
                .DisposeWith(disposables);

                this.SearchResults = searchResultsBinding;

                Search =
                    ReactiveCommand
                    .CreateFromTask(
                        async(ct) =>
                {
                    var worldNews = await RssDownloader.DownloadRss("https://www.reddit.com/r/worldnews/new/.rss", ct).ConfigureAwait(false);

                    _searchResultSource
                    .Edit(
                        innerList =>
                    {
                        innerList.Clear();
                        innerList.AddRange(worldNews);
                    });
                })
                    .DisposeWith(disposables);
            });
        }
예제 #4
0
        public SortDynamicDataViewModel()
        {
            this.WhenActivated((CompositeDisposable disposables) =>
            {
                _searchResultSource = new SourceList <RssEntry>().DisposeWith(disposables);

                var sorter =
                    this.WhenAnyValue(x => x.SelectedSortType)
                    .Select(
                        SelectedSortType =>
                {
                    switch (SelectedSortType)
                    {
                    case SortType.DateTimeAscending:
                        return(SortExpressionComparer <RssEntry> .Ascending(x => x.Updated));

                    case SortType.DateTimeDescending:
                        return(SortExpressionComparer <RssEntry> .Descending(x => x.Updated));

                    case SortType.TitleAscending:
                        return(SortExpressionComparer <RssEntry> .Ascending(x => x.Title));

                    case SortType.TitleDescending:
                    default:
                        return(SortExpressionComparer <RssEntry> .Descending(x => x.Title));
                    }
                });

                _searchResultSource
                .Connect()
                .SubscribeOn(RxApp.TaskpoolScheduler)
                .Sort(sorter)
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out var searchResultsBinding)
                .Subscribe()
                .DisposeWith(disposables);

                this.SearchResults = searchResultsBinding;

                Search =
                    ReactiveCommand
                    .CreateFromTask(
                        async(ct) =>
                {
                    var worldNews = await RssDownloader.DownloadRss("https://www.reddit.com/r/worldnews/new/.rss", ct).ConfigureAwait(false);

                    _searchResultSource
                    .Edit(
                        innerList =>
                    {
                        innerList.Clear();
                        innerList.AddRange(worldNews);
                    });
                })
                    .DisposeWith(disposables);
            });
        }
예제 #5
0
        public void Parse_RssDownloader_module()
        {
            var xdoc     = XDocument.Load("XmlSamples\\RssModule.xml");
            var xelement = xdoc.Root.Element("Module");

            var           moduleRunner = new ModuleRunner();
            RssDownloader module       = moduleRunner.ParseRssDownloader(xelement);

            Assert.AreEqual("RssDownloader01", module.Name);
            Assert.IsTrue(module.ContentMatcher.Match("dexter.mkv"));
        }
        public SourceCacheDynamicDataViewModel()
        {
            this.WhenActivated((CompositeDisposable disposables) =>
            {
                _searchResultSource = new SourceCache <RssEntry, string>(x => x.Id).DisposeWith(disposables);

                _searchResultSource
                .Connect()
                .SubscribeOn(RxApp.TaskpoolScheduler)
                .OnItemAdded(x => x.New = true)
                .OnItemUpdated((current, previous) => current.New = false)
                .Sort(
                    SortExpressionComparer <RssEntry>
                    .Descending(x => x.New)
                    .ThenByDescending(x => x.Updated))
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out var searchResultsBinding)
                .Subscribe()
                .DisposeWith(disposables);

                this.SearchResults = searchResultsBinding;

                Search =
                    ReactiveCommand
                    .CreateFromTask(
                        async(ct) =>
                {
                    var rss = await RssDownloader.DownloadRss("https://www.reddit.com/r/worldnews/new/.rss", ct).ConfigureAwait(false);

                    _searchResultSource.AddOrUpdate(rss);
                })
                    .DisposeWith(disposables);

                Observable
                .Interval(TimeSpan.FromSeconds(5))
                .SelectUnit()
                .InvokeCommand(this, x => x.Search)
                .DisposeWith(disposables);
            });
        }
예제 #7
0
        Task <IEnumerable <RssEntry> > DownloadMultipleRss(CancellationToken ct)
        {
            return(Task.Run <IEnumerable <RssEntry> >(async() =>
            {
                System.Diagnostics.Debug.WriteLine($"Starting download at {DateTimeOffset.Now}");

                var askReddit = RssDownloader.DownloadRss("https://www.reddit.com/r/AskReddit/new/.rss", ct);
                var todayILearned = RssDownloader.DownloadRss("https://www.reddit.com/r/todayilearned/new/.rss", ct);
                var news = RssDownloader.DownloadRss("https://www.reddit.com/r/news/new/.rss", ct);
                var worldNews = RssDownloader.DownloadRss("https://www.reddit.com/r/worldnews/new/.rss", ct);

                var tcs = new TaskCompletionSource <object>();

                ct.Register(() => tcs.TrySetCanceled(), false);

                await Task.WhenAny(Task.WhenAll(askReddit, todayILearned, news, worldNews), tcs.Task).ConfigureAwait(false);

                var masterList = new List <RssEntry>();

                if (!ct.IsCancellationRequested && !tcs.Task.IsCanceled)
                {
                    masterList.AddRange(await askReddit.ConfigureAwait(false));
                    masterList.AddRange(await todayILearned.ConfigureAwait(false));
                    masterList.AddRange(await news.ConfigureAwait(false));
                    masterList.AddRange(await worldNews.ConfigureAwait(false));
                }

                var filteredList = masterList.GroupBy(x => x.Id).Select(x => x.First()).ToList();

                if (ct.IsCancellationRequested)
                {
                    System.Diagnostics.Debug.WriteLine($"Cancelled download at {DateTimeOffset.Now}");
                    return Enumerable.Empty <RssEntry>();
                }

                return filteredList;
            }));
        }
        public SimpleDynamicDataViewModel()
        {
            this.WhenActivated((CompositeDisposable disposables) =>
            {
                _searchResultSource = new SourceList <RssEntry>().DisposeWith(disposables);

                var filter =
                    this.WhenAnyValue(x => x.SearchQuery)
                    .SubscribeOn(RxApp.MainThreadScheduler)
                    .Select(
                        search =>
                {
                    var searchIsEmpty = string.IsNullOrEmpty(search);

                    return(new Func <RssEntry, bool>(
                               value =>
                    {
                        if (searchIsEmpty)
                        {
                            return true;
                        }

                        return FuzzySharp.Fuzz.PartialRatio(value.Title, search) > 75;
                    }));
                });

                var filteredData =
                    _searchResultSource
                    .Connect()
                    .SubscribeOn(RxApp.MainThreadScheduler)
                    .Filter(filter)
                    .Publish()
                    .RefCount();

                filteredData
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out var searchResultsBinding)
                .Subscribe()
                .DisposeWith(disposables);

                this.SearchResults = searchResultsBinding;

                filteredData
                .Count()
                .BindTo(this, x => x.ResultCount)
                .DisposeWith(disposables);

                Search =
                    ReactiveCommand
                    .CreateFromTask(
                        async(ct) =>
                {
                    var worldNews = await RssDownloader.DownloadRss("https://www.reddit.com/r/worldnews/new/.rss", ct).ConfigureAwait(false);

                    _searchResultSource
                    .Edit(
                        innerList =>
                    {
                        innerList.Clear();
                        innerList.AddRange(worldNews);
                    });
                })
                    .DisposeWith(disposables);
            });
        }
        public FilterDynamicDataViewModel()
        {
            this.WhenActivated((CompositeDisposable disposables) =>
            {
                _searchResultSource = new SourceList <RssEntry>().DisposeWith(disposables);

                var filter =
                    this.WhenAnyValue(x => x.SearchQuery)
                    .SubscribeOn(RxApp.TaskpoolScheduler)
                    .Select(
                        search =>
                {
                    var searchIsEmpty = string.IsNullOrEmpty(search);

                    return(new Func <RssEntry, bool>(
                               value =>
                    {
                        if (searchIsEmpty)
                        {
                            return true;
                        }

                        return FuzzySharp.Fuzz.PartialRatio(value.Title, search) > 75;
                    }));
                });

                var filteredData =
                    _searchResultSource
                    .Connect()
                    .SubscribeOn(RxApp.MainThreadScheduler)
                    .Filter(filter)
                    .Publish()
                    .RefCount();

                filteredData
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out var searchResultsBinding)
                .Subscribe()
                .DisposeWith(disposables);

                this.SearchResults = searchResultsBinding;

                filteredData
                .Count()
                .BindTo(this, x => x.ResultCount)
                .DisposeWith(disposables);

                CancelSearch =
                    ReactiveCommand
                    .Create(() => {})
                    .DisposeWith(disposables);

                Search =
                    ReactiveCommand
                    .CreateFromObservable(
                        () =>
                {
                    return(Observable
                           .StartAsync(
                               async(ct) =>
                    {
                        var worldNews = await RssDownloader.DownloadRss("https://www.reddit.com/r/worldnews/new/.rss", ct).ConfigureAwait(false);

                        if (ct.IsCancellationRequested)
                        {
                            return;
                        }

                        _searchResultSource
                        .Edit(
                            innerList =>
                        {
                            innerList.Clear();
                            innerList.AddRange(worldNews);
                        });
                    })
                           .TakeUntil(this.CancelSearch)
                           .SelectUnit());
                })
                    .DisposeWith(disposables);

                Observable
                .Merge(
                    this.ThrownExceptions,
                    Search.ThrownExceptions)
                .Do(ex => System.Diagnostics.Debug.WriteLine($"ERROR!!: {ex}"));
            });
        }