示例#1
0
        public void NewAnimated_Returns_PageAndImage()
        {
            var stub = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null         //в этом тесте новых страниц нет, поэтому первый селектор вернет null
            };

            IPageSelector pageSelectorForNewPages = stub;

            //а главную "роль" в тесте исполнит селектор новых аним.изображений - он должен вернуть
            AnimatedImage animatedImage = new AnimatedImage
            {
                BlobName  = "code-geass:img1.gif",
                TweetDate = null                 //гифка новая даты твита не должно быть
            };

            var animNewStub = new Stubs.AnimatedSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = new AnimatedImage[] { animatedImage }       //стаб вернет этот результат
            };

            IFindAnimatedByPage animatedSelectorForNewImages = animNewStub;

            //в этом тесте ожидается работа стаба FindPageByBlobNameStub - он должен "найти" страницу по имени блоба
            SitePage page = new SitePage
            {
                URL = "https://dummy/code-geass"
            };

            var findPageByBlob = new Stubs.FindPageByBlobNameStub
            {
                DontThrowNotImpl = true,
                Result           = page
            };

            //имитируем найденную страницу...
            IFindPageByBlobName findPageByBlobName = findPageByBlob;

            IPageSelector                    pageSelectorForAnyPages         = new Stubs.PageSelectorStub();
            IFindAnimatedByPage              findAnimatedByPage              = new Stubs.FindAnimatedByPageStub();
            IPageOrExternalImageSelector     pageOrExternalImageSelector     = new Stubs.PageOrExternalImageSelectorStub();
            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub();

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;

            //проверяем что он вернул
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Page);
            Assert.IsNotNull(result.Image);

            //для поиска должны передать строго то имя блоба, что мы предусмотрели тестом
            Assert.IsTrue(findPageByBlob.UsedBlobNameForFind == animatedImage.BlobName);

            Assert.AreSame(page, result.Page);
            Assert.AreSame(animatedImage, result.Image);
        }
示例#2
0
        public void NewPageFound_Returns_This_Page()
        {
            SitePage page = new SitePage
            {
                URL = "https://dummy/url"
            };

            //pageSelectorForNewPages в данном тесте имеет осмысленную реализацию и выдает всегда одну страницу
            var stub = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = page
            };

            IPageSelector pageSelectorForNewPages = stub;

            IFindAnimatedByPage              animatedSelectorForNewImages    = new Stubs.AnimatedSelectorStub();
            IPageSelector                    pageSelectorForAnyPages         = new Stubs.PageSelectorStub();
            IFindAnimatedByPage              findAnimatedByPage              = new Stubs.FindAnimatedByPageStub();
            IPageOrExternalImageSelector     pageOrExternalImageSelector     = new Stubs.PageOrExternalImageSelectorStub();
            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub();

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;

            //проверяем что он вернул
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Page);
            Assert.IsNull(result.Image, "Не очікувалося заповнення TwittData.Image");

            Assert.AreSame(page, result.Page);
        }
示例#3
0
        void _PageFoundBody(AnimatedImage[] resultForFindAnimated)
        {
            SitePage page = new SitePage
            {
                URL = "https://dummy/url"
            };

            //pageSelectorForNewPages в данном тесте выдает null чтобы логика прошла дальше (нет новых страниц)
            var stubNewPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            //этот стаб вернет null (нет новых аним.изображений)
            var animNewStub = new Stubs.AnimatedSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };


            IPageSelector       pageSelectorForNewPages      = stubNewPages;
            IFindAnimatedByPage animatedSelectorForNewImages = animNewStub;

            IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub();

            var stubAnyPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = page
            };
            //Главный "герой" этого теста - должен вернуть одну страницу (ее когда-то твитили, но уже давно)
            IPageSelector pageSelectorForAnyPages = stubAnyPages;


            //в нашем тесте этот универсальный поиск выдает null (нет аним.изображений для страницы)
            var stubFindAnimated = new Stubs.FindAnimatedByPageStub
            {
                DontThrowNotImpl = true,
                Result           = resultForFindAnimated
            };

            IFindAnimatedByPage findAnimatedByPage = stubFindAnimated;

            IPageOrExternalImageSelector     pageOrExternalImageSelector     = new Stubs.PageOrExternalImageSelectorStub();
            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub();

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;

            //проверяем что он вернул
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Page);
            Assert.IsNull(result.Image, "Не очікувалося заповнення TwittData.Image");

            Assert.AreSame(page, result.Page);
        }
示例#4
0
        public void NewAnimated_FindPageByBlobName_Returns_Null_Exception()
        {
            var stub = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null         //в этом тесте новых страниц нет, поэтому первый селектор вернет null
            };

            IPageSelector pageSelectorForNewPages = stub;

            //это часть урла, а блоб всегда содержит в начале такое же (до двоеточия)
            string codeGeassURLPart = "code-geass";

            //а главную "роль" в тесте исполнит селектор новых аним.изображений - он должен вернуть
            AnimatedImage animatedImage = new AnimatedImage
            {
                BlobName  = "code-geass:img1.gif",
                TweetDate = null                 //гифка новая даты твита не должно быть
            };

            var animNewStub = new Stubs.AnimatedSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = new AnimatedImage[] { animatedImage }       //стаб вернет этот результат
            };

            IFindAnimatedByPage animatedSelectorForNewImages = animNewStub;

            //в этом тесте ожидается работа стаба FindPageByBlobNameStub - он должен НЕ найти страницу по имени блоба (вернуть null)
            //и это приведет в итоге к исключению
            var findPageByBlob = new Stubs.FindPageByBlobNameStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            //имитируем найденную страницу...
            IFindPageByBlobName findPageByBlobName = findPageByBlob;

            IPageSelector                    pageSelectorForAnyPages         = new Stubs.PageSelectorStub();
            IFindAnimatedByPage              findAnimatedByPage              = new Stubs.FindAnimatedByPageStub();
            IPageOrExternalImageSelector     pageOrExternalImageSelector     = new Stubs.PageOrExternalImageSelectorStub();
            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub();

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            try
            {
                TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;
            }
            catch (AggregateException aggrEx)
            {
                ApplicationException appEx = (ApplicationException)aggrEx.InnerExceptions[0];

                //это и должно было произойти. В тексте наш спец.текст
                Assert.IsTrue(appEx.Message.Contains("Find page by blob name failed for"));
                Assert.IsTrue(appEx.Message.Contains(codeGeassURLPart));
            }
        }
示例#5
0
        public void No_Page_For_Twitting()
        {
            //этот аналог важен для покрытия кода

            var stubNewPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            //этот стаб вернет null (нет новых аним.изображений)
            var animNewStub = new Stubs.AnimatedSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            IPageSelector       pageSelectorForNewPages      = stubNewPages;
            IFindAnimatedByPage animatedSelectorForNewImages = animNewStub;

            IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub();

            var stubAnyPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null         //Это ситуация которую моделирует тест - такое не должно быть в реальной системе (и будет выброс исключения)
            };
            IPageSelector pageSelectorForAnyPages = stubAnyPages;

            //в нашем тесте этот универсальный поиск выдает null (нет аним.изображений для страницы)
            var stubFindAnimated = new Stubs.FindAnimatedByPageStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            IFindAnimatedByPage              findAnimatedByPage              = stubFindAnimated;
            IPageOrExternalImageSelector     pageOrExternalImageSelector     = new Stubs.PageOrExternalImageSelectorStub();
            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub();

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            try
            {
                TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;
                Assert.Fail("Ожидался выброс исключения ApplicationException так как селектор pageSelectorForAnyPages вернул null (чего быть в работе не должно никогда)");
            }
            catch (System.AggregateException aggrEx)
            {
                ApplicationException appEx = (ApplicationException)aggrEx.InnerExceptions[0];

                //это и должно было произойти. В тексте наш спец.текст
                Assert.IsTrue(appEx.Message.Contains("No page found for twitting"));
            }
        }
示例#6
0
        public void PageFound_And_AnimatedFound_Random_Select_PageOnly()
        {
            //Тест-кейс: найдена не-новая страница и у нее есть внешние изображения. Рандомизированный выбор "решил" что их не нужно использовать
            SitePage page = new SitePage
            {
                URL = "https://dummy/url"
            };

            //pageSelectorForNewPages в данном тесте выдает null чтобы логика прошла дальше (нет новых страниц)
            var stubNewPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            //этот стаб вернет null (нет новых аним.изображений)
            var animNewStub = new Stubs.AnimatedSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };


            IPageSelector       pageSelectorForNewPages      = stubNewPages;
            IFindAnimatedByPage animatedSelectorForNewImages = animNewStub;

            IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub();

            var stubAnyPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = page
            };
            //Главный "герой" этого теста - должен вернуть одну страницу (ее когда-то твитили, но уже давно)
            IPageSelector pageSelectorForAnyPages = stubAnyPages;

            //аним.изображения найдены, но их не будем использовать
            AnimatedImage[] animatedImgs = new AnimatedImage[]
            {
                //здесь нам не важно что - оно просто должно быть, тест "не выбирает" это
                new AnimatedImage()
                {
                    BlobName = "dummy", TweetDate = new DateTime(2020, 04, 26, 00, 00, 00)
                }
            };

            var stubFindAnimated = new Stubs.FindAnimatedByPageStub
            {
                DontThrowNotImpl = true,
                Result           = animatedImgs
            };

            IFindAnimatedByPage findAnimatedByPage = stubFindAnimated;

            //этот стаб имитирует "случайное решение" о том использовать ли изобр.со страницы , или внешнее анимированное.
            //В этом тесте он всегда выбирает "со страницы"
            var stubRandomPageOrImg = new Stubs.PageOrExternalImageSelectorStub();

            stubRandomPageOrImg.DontThrowNotImpl         = true;
            stubRandomPageOrImg.UseExternalAnimatedImage = false;               //именно это важно для данного теста

            IPageOrExternalImageSelector pageOrExternalImageSelector = stubRandomPageOrImg;

            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub();

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;

            //проверяем что он вернул
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Page);
            Assert.IsNull(result.Image, "Не очікувалося заповнення TwittData.Image");

            Assert.AreSame(page, result.Page);
        }
示例#7
0
        public void PageFound_And_AnimatedFound_Random_Select_Animated()
        {
            //Тест-кейс: найдена не-новая страница и у нее есть внешние изображения. Рандомизированный выбор "решил" использовать одно из них
            SitePage page = new SitePage
            {
                URL = "https://kawaii-mobile.com/oregairu"
            };

            //pageSelectorForNewPages в данном тесте выдает null чтобы логика прошла дальше (нет новых страниц)
            var stubNewPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };

            //этот стаб вернет null (нет новых аним.изображений)
            var animNewStub = new Stubs.AnimatedSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = null
            };


            IPageSelector       pageSelectorForNewPages      = stubNewPages;
            IFindAnimatedByPage animatedSelectorForNewImages = animNewStub;

            IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub();

            var stubAnyPages = new Stubs.PageSelectorStub
            {
                DontThrowNotImpl = true,
                Result           = page
            };
            IPageSelector pageSelectorForAnyPages = stubAnyPages;

            var anim1 = new AnimatedImage
            {
                BlobName  = "oregairu:img1.gif",
                TweetDate = new DateTime(2020, 04, 26, 00, 00, 00)
            };

            var anim2 = new AnimatedImage
            {
                BlobName  = "oregairu:yukinoshita.gif",
                TweetDate = new DateTime(2020, 01, 10, 22, 10, 00)
            };

            var anim3 = new AnimatedImage
            {
                BlobName  = "oregairu:hatiman.gif",
                TweetDate = new DateTime(2020, 02, 08, 08, 00, 00)
            };

            //аним.изображения найдены, тест использует всегда одно из них (anim2)
            AnimatedImage[] animatedImgs = new AnimatedImage[] { anim1, anim2, anim3 };

            var stubFindAnimated = new Stubs.FindAnimatedByPageStub
            {
                DontThrowNotImpl = true,
                Result           = animatedImgs
            };

            IFindAnimatedByPage findAnimatedByPage = stubFindAnimated;

            //этот стаб имитирует "случайное решение" о том использовать ли изобр.со страницы , или внешнее анимированное.
            //В этом тесте он всегда выбирает "со страницы"
            var stubRandomPageOrImg = new Stubs.PageOrExternalImageSelectorStub();

            stubRandomPageOrImg.DontThrowNotImpl         = true;
            stubRandomPageOrImg.UseExternalAnimatedImage = true;               //именно это важно для данного теста

            IPageOrExternalImageSelector pageOrExternalImageSelector = stubRandomPageOrImg;

            var animSelectorStub = new Stubs.AnimatedSelectorWithExcludeLastStub
            {
                DontThrowNotImpl = true,
                Result           = anim2
            };

            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = animSelectorStub;

            var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger());

            TwittData result = pageForTwittingSelector.GetPageForTwitting().Result;

            //проверяем что он вернул
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Page);

            //в тесте ожидается что вернут и изображение что мы указали
            Assert.IsNotNull(result.Image);
            Assert.AreSame(result.Image, anim2);

            Assert.AreSame(page, result.Page);
        }
示例#8
0
        public static async Task Run([TimerTrigger("0 0 * * * *")] TimerInfo timer, ILogger log)
        {
            //https://docs.microsoft.com/ru-ru/azure/azure-functions/functions-bindings-timer?tabs=csharp#ncrontab-expressions
            //0 */5 * * * * - каждые 5 мин
            //"0 0 * * * *"	- каждый час

            Logger logger = new Logger(log);

            logger.Log($"TweetPostFunction executed at: {DateTime.Now}");

            string animatedBlobConnectionString = kawaii.twitter.core.Env.EnvironmentSecureData.GetValueFromEnvironment("env:kawaii_twitter_azure_animatedblob");
            string azureSiteDBConnectionString  = kawaii.twitter.core.Env.EnvironmentSecureData.GetValueFromEnvironment("env:kawaii_twitter_azure_sitepages");

            if (string.IsNullOrEmpty(animatedBlobConnectionString))
            {
                logger.LogError("animatedBlobConnectionString not found!");
                return;
            }

            if (string.IsNullOrEmpty(azureSiteDBConnectionString))
            {
                logger.LogError("azureSiteDBConnectionString not found!");
                return;
            }

            IDatabase database = new Database(azureSiteDBConnectionString, true, null);

            logger.Log($"database connected: {DateTime.Now}");

            //если в переменных задано что "не обновлять индексы", то мы сэкономим время работы в прод-окружении - индексы создаются один раз,
            //и дальше и так работают, хотя MongoDB и говорит что "нет проблем".
            //Если будет нужно обновлять индексы, или будет новое окружение (новая база, коллекция и прочее) то эту переменную среды надо убрать.
            //А когда все настроено и уже работает, ее можно создать для общего ускорения
            string dontCreateIndexesStr = kawaii.twitter.core.Env.EnvironmentSecureData.GetValueFromEnvironment("env:kawaii_twitter_dont_create_indexes");
            bool   dontCreateIndexes    = false;

            if (!string.IsNullOrEmpty(dontCreateIndexesStr))
            {
                bool.TryParse(dontCreateIndexesStr, out dontCreateIndexes);
            }

            if (dontCreateIndexes)
            {
                logger.Log("Indexes will not updated (found env:kawaii_twitter_dont_create_indexes)");
            }

            AnimatedImageCollection animatedImageCollection = new AnimatedImageCollection(database, null, !dontCreateIndexes);
            var imagesCollection = animatedImageCollection.AnimatedImages;

            logger.Log($"imagesCollection init done: {DateTime.Now}");

            SitePageCollection sitePageCollection = new SitePageCollection(database, null, !dontCreateIndexes);
            var sitePagesCollection = sitePageCollection.SitePages;

            logger.Log($"sitePagesCollection init done: {DateTime.Now}");

            ITwitterTextCreator textCreator     = new kawaii.twitter.core.Text.TwitterTextCreator();
            IImageOnWeb         imageOnWeb      = new kawaii.twitter.core.HtmlParsers.ImageOnWeb(_HttpClient);
            ITwitterImageURL    twitterImageURL = new kawaii.twitter.core.HtmlParsers.TwitterImageURL(_HttpClient);

            //--- блок для lastTweetUpdater
            var dateSupply = new kawaii.twitter.core.Env.DateSupply();

            IAnimatedTweetDateUpdater animatedTweetDateUpdater = new AnimatedTweetDateUpdater(imagesCollection);
            ISitePageTweetDateUpdater sitePageTweetDateUpdater = new SitePageTweetDateUpdater(sitePagesCollection);
            ILastTweetUpdater         lastTweetUpdater         = new kawaii.twitter.core.SelectLogic.LastTweetUpdater(dateSupply, animatedTweetDateUpdater, sitePageTweetDateUpdater);
            //---

            //сервису твиттера нужно передать авториз.данные
            var service = new kawaii.twitter.core.TwitterService.Service();

            var           animatedImagesBlobContainer = new AnimatedImagesBlobContainer(animatedBlobConnectionString);
            IBlobDownload blobDownload = animatedImagesBlobContainer;

            var randomSelector = new kawaii.twitter.core.SelectLogic.Randomize.RandomSelector();

            int topQueryCount = 10;

            ISpecialDaySelector specialDaySelector = new SpecialDaySelector(dateSupply, randomSelector);
            string specialDayName = specialDaySelector.DetectSpecialDayName();

            IFolderFromURL folderFromURL = new kawaii.twitter.core.SelectLogic.URL.FolderFromURL();
            var            formatter     = new kawaii.twitter.core.SelectLogic.BlobName.Formatter();

            IPageSelector       pageSelectorForNewPages = new kawaii.twitter.core.SelectLogic.Page.NotTwittedPages(sitePagesCollection, randomSelector, specialDayName, topQueryCount);
            IFindAnimatedByPage findNewAnimatedByPage   = new kawaii.twitter.core.SelectLogic.Images.Newly.NotTwittedAnimated(imagesCollection, randomSelector, topQueryCount, folderFromURL, formatter);

            IPageSelector pageSelectorForAnyPages = new kawaii.twitter.core.SelectLogic.Page.PageSelector(sitePagesCollection, randomSelector, specialDayName, topQueryCount);

            IFindAnimatedByPage findAnimatedByPage = new kawaii.twitter.core.SelectLogic.Images.Find.FindAnimatedByPage(imagesCollection.AsQueryable(), folderFromURL, formatter);

            IPageOrExternalImageSelector pageOrExternalImageSelector = new kawaii.twitter.core.SelectLogic.PageOrExternalImage.PageOrExternalImageSelector();

            IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new kawaii.twitter.core.SelectLogic.Images.ExcludeUsed.AnimatedSelectorWithExcludeLast();

            IPageForTwittingSelector pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, findNewAnimatedByPage, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, logger);

            var tweetCreator = new kawaii.twitter.core.TweetCreator(pageForTwittingSelector, textCreator, twitterImageURL, imageOnWeb, blobDownload, service, lastTweetUpdater, logger);

            logger.Log($"tweetCreator.Execute: {DateTime.Now}");

            //выполнить твит заданной страницы и изображения
            await tweetCreator.Execute();
        }