예제 #1
0
        public async Task <IEnumerable <News> > GenerateAsync()
        {
            //Order of adding important
            var generatedNews = new List <News>();

            foreach (var source in _sourceConfiguration.Sources)
            {
                var componentsFabric = ComponentsProvider.CreateComponentsFactory(source.SiteTitle);
                var sourceGenerator  = componentsFabric.CreateSourceGenertor();
                var sourceValidator  = componentsFabric.CreateSourceValidator();
                var htmlParser       = componentsFabric.CreateNewsParser();

                var newsBySource = _newsRepository.Read(n => n.Source.SiteTitle == source.SiteTitle);
                var lastNews     = newsBySource.OrderByDescending(n => n.Id).FirstOrDefault();

                var partsOfNews = new List <PartOfNews>();
                IEnumerable <string> sourcesUrl      = null;
                ICollection <News>   newNewsBySource = null;
                var isNeedContinue   = false;
                var isLastNewsFinded = false;
                var skipNews         = 0;

                do
                {
                    sourcesUrl = await sourceGenerator.GenerateAsync(source.SiteTemplate, _sourceConfiguration.CountGeneratedNewsFor1Time, skipNews);

                    sourcesUrl = await sourceValidator.ValidateAsync(sourcesUrl);

                    sourcesUrl = sourcesUrl.Reverse();

                    newNewsBySource = new List <News>();

                    foreach (var sourceUrl in sourcesUrl)
                    {
                        var news = await htmlParser.ParseAsync(sourceUrl);

                        if (news.Equals(lastNews) || lastNews == null)
                        {
                            isLastNewsFinded = true;
                        }

                        newNewsBySource.Add(news);
                    }

                    var partOfNews = new PartOfNews()
                    {
                        News = newNewsBySource,
                        IsPageHaveLastNews = isLastNewsFinded
                    };

                    partsOfNews.Add(partOfNews);
                    skipNews += _sourceConfiguration.CountGeneratedNewsFor1Time;

                    isNeedContinue = !isLastNewsFinded &&
                                     sourcesUrl.Count() > 0 &&
                                     skipNews < _sourceConfiguration.MaxScaningNewsIfLastNewsNotFound;
                }while (isNeedContinue);

                if (isLastNewsFinded)
                {
                    for (int i = partsOfNews.Count - 1; i >= 0; i--)
                    {
                        var part = partsOfNews[i];

                        if (part.IsPageHaveLastNews)
                        {
                            isLastNewsFinded = false;

                            foreach (var news in part.News)
                            {
                                if (isLastNewsFinded)
                                {
                                    generatedNews.Add(news);
                                }

                                if (news.Equals(lastNews) || lastNews == null)
                                {
                                    isLastNewsFinded = true;
                                }
                            }
                        }
                        else
                        {
                            generatedNews.AddRange(part.News);
                        }
                    }
                }
                else
                {
                    var newLastNews = partsOfNews.FirstOrDefault().News.LastOrDefault();
                    generatedNews.Add(newLastNews);
                }
            }

            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var infoGenerators = scope.ServiceProvider.GetServices <IInfoGenerator>();
                var generatorTasks = new List <Task>();

                foreach (var generator in infoGenerators)
                {
                    var task = generator.ProcessAsync(generatedNews);
                    generatorTasks.Add(task);
                }

                await Task.WhenAll(generatorTasks);
            }

            if (generatedNews.Count > 0)
            {
                await _newsRepository.BulkInsertAsync(generatedNews);
            }

            return(generatedNews);
        }