示例#1
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            using var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false);

            await page.SetViewportAsync(new ViewPortOptions
            {
                DeviceScaleFactor = 3.5,
                Width             = 800,
                Height            = 1000,
            }).ConfigureAwait(false);

            await page.GoToAsync("https://www.investing.com/indices/us-spx-500-futures").ConfigureAwait(false);

            const string selector = "#quotes_summary_current_data";
            var          element  = await page.QuerySelectorAsync(selector).ConfigureAwait(false);

            var data = await element.ScreenshotDataAsync(new ScreenshotOptions
            {
                Type = ScreenshotType.Png,
            }).ConfigureAwait(false);

            bool inLoop = true;
            int  retry  = 3;

            do
            {
                var mesResponse = await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false);

                inLoop = mesResponse == null;
            } while (inLoop && --retry > 0);
        }
示例#2
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            using var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false);

            await page.SetViewportAsync(new ViewPortOptions
            {
                DeviceScaleFactor = 3,
                Width             = 360,
                Height            = 8000,
            }).ConfigureAwait(false);

            await page.GoToAsync("https://toyokeizai.net/sp/visual/tko/covid19/en.html").ConfigureAwait(false);

            await page.WaitForSelectorAsync("#main-block > div:nth-child(2) > div:nth-child(1) > div > div.charts-wrapper > div.main-chart-wrapper > div > canvas").ConfigureAwait(false);

            var element = await page.QuerySelectorAsync("#main-block > div:nth-child(2)").ConfigureAwait(false);

            await page.SetViewportAsync(new ViewPortOptions
            {
                DeviceScaleFactor = 2,
                Width             = 1024,
                Height            = 4000,
            }).ConfigureAwait(false);

            var data2 = await element.ScreenshotDataAsync(new ScreenshotOptions
            {
                Type    = ScreenshotType.Jpeg,
                Quality = 100,
            }).ConfigureAwait(false);

            await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data2)).ConfigureAwait(false);
        }
    public async Task ProcessAsync(MessageContext context, HttpApiClient api)
    {
        using var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false);

        await page.SetViewportAsync(new ViewPortOptions
        {
            DeviceScaleFactor = 3,
            Width             = 360,
            Height            = 8000,
        }).ConfigureAwait(false);

        await page.GoToAsync("https://en.wikipedia.org/wiki/Template:COVID-19_pandemic_data/Canada_medical_cases_by_province").ConfigureAwait(false);

        var element = await page.QuerySelectorAsync("#mw-content-text > div.mw-parser-output > table").ConfigureAwait(false);

        await page.SetViewportAsync(new ViewPortOptions
        {
            DeviceScaleFactor = 2,
            Width             = 1024,
            Height            = 4000,
        }).ConfigureAwait(false);

        var data2 = await element.ScreenshotDataAsync(new ScreenshotOptions
        {
            Type    = ScreenshotType.Jpeg,
            Quality = 100,
        }).ConfigureAwait(false);

        await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data2)).ConfigureAwait(false);
    }
示例#4
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            string url       = "https://rss.bleatingsheep.org/zhihu/daily";
            var    xmlReader = XmlReader.Create(url);
            var    feed      = SyndicationFeed.Load(xmlReader);

            xmlReader.Close();
            var item = feed.Items.LastOrDefault();

            if (item != default)
            {
                bool modified = false;
                var  doc      = new HtmlDocument();
                var  htmlText = item.Summary.Text;
                doc.LoadHtml(htmlText);
                foreach (var imgNode in doc.DocumentNode.SelectNodes("//div/div/div/div/div/p/img")?.Where(n => n.GetClasses().FirstOrDefault() == "content-image") ?? Enumerable.Empty <HtmlNode>())
                {
                    imgNode.SetAttributeValue("width", "100%");
                    modified = true;
                }
                if (modified)
                {
                    htmlText = doc.DocumentNode.InnerHtml;
                }

                using (var page = await Chrome.OpenNewPageAsync())
                {
                    await page.SetContentAsync(htmlText);

                    await page.SetViewportAsync(new ViewPortOptions
                    {
                        DeviceScaleFactor = 1.5,
                        Width             = 360,
                        Height            = 640,
                    });

                    var data = await page.ScreenshotDataAsync(new ScreenshotOptions
                    {
                        FullPage = true,
                    });

                    await Task.Delay(100);

                    var sendCode = await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data));

                    if (sendCode == null)
                    {
                        Logger.Info("知乎日报发送失败。");
                    }
                }
            }
        }
示例#5
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            Logger.Debug($"开始读取 URL {Url} ");
            using (var httpClient = new HttpClient())
            {
                var data = await httpClient.GetByteArrayAsync(Url);

                Logger.Debug($"取到 {data.Length} 字节数据。");
                var sendResponse = await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data));

                Logger.Debug($"发送结果:消息 ID {sendResponse?.MessageId.ToString(CultureInfo.InvariantCulture) ?? "null"}");
            }
        }
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            int  uid;
            Mode mode;

            try { mode = ModeExtensions.Parse(ModeString); }
            catch { mode = default; }

            if (string.IsNullOrEmpty(Name))
            {
                uid = await EnsureGetBindingIdAsync(context.UserId).ConfigureAwait(false);
            }
            else
            {
                var user = await EnsureGetUserInfo(Name, Mode.Standard).ConfigureAwait(false);

                uid = user.Id;
            }
            string url = $"https://info.osustuff.ri.mk/cn/users/{uid}/{s_modes.GetValueOrDefault(mode)}";

            using var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false);

            await page.SetViewportAsync(new ViewPortOptions
            {
                DeviceScaleFactor = Math.Sqrt(0.5),
                Width             = 1058,
                Height            = 80,
            }).ConfigureAwait(false);

            _ = await page.GoToAsync(url, WaitUntilNavigation.Networkidle0).ConfigureAwait(false);

            await page.WaitForTimeoutAsync(500).ConfigureAwait(false);

            var data = await page.ScreenshotDataAsync(new ScreenshotOptions
            {
                FullPage = true,
                Type     = ScreenshotType.Jpeg,
                Quality  = 100,
            }).ConfigureAwait(false);

            _ = await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false);
        }
示例#7
0
    public async Task ProcessAsync(MessageContext context, HttpApiClient api)
    {
        using var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false);

        await page.SetViewportAsync(new ViewPortOptions
        {
            DeviceScaleFactor = 3,
            Width             = 360,
            Height            = 8000,
        }).ConfigureAwait(false);

        await page.GoToAsync("https://www.nytimes.com/interactive/2021/us/covid-cases.html").ConfigureAwait(false);

        await page.WaitForSelectorAsync("#us-covid-cases > div > div > main > div.g-columns-outer.svelte-hfvvmm > div:nth-child(2) > section:nth-child(1)").ConfigureAwait(false);

        var deleteElement = await page.QuerySelectorAsync("#standalone-footer > div > div").ConfigureAwait(false);

        await deleteElement.EvaluateFunctionAsync("b => b.remove()").ConfigureAwait(false);

        var element = await page.QuerySelectorAsync("#us-covid-cases > div > div > main > div.g-columns-outer.svelte-hfvvmm > div:nth-child(2) > section:nth-child(1)").ConfigureAwait(false);

        await page.SetViewportAsync(new ViewPortOptions
        {
            DeviceScaleFactor = 2,
            Width             = 1024,
            Height            = 4000,
        }).ConfigureAwait(false);

        var data2 = await element.ScreenshotDataAsync(new ScreenshotOptions
        {
            Type    = ScreenshotType.Jpeg,
            Quality = 100,
        }).ConfigureAwait(false);

        await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data2)).ConfigureAwait(false);
    }
示例#8
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            string url       = "https://rsshub.app/pixiv/ranking/day";
            var    xmlReader = XmlReader.Create(url);
            var    feed      = SyndicationFeed.Load(xmlReader);
            var    tuple     = feed.Items.Select(i =>
            {
                var doc = new HtmlDocument();
                doc.LoadHtml(i.Summary.Text);
                return(item: i, nodes: doc.DocumentNode.SelectNodes("//p/img"));
            }).Randomize().FirstOrDefault(t => t.nodes.Count == 1);

            var(item, imgNode) = (tuple.item, tuple.nodes?.First());
            if (imgNode != null)
            {
                var imgUrl = imgNode.Attributes["src"].Value;
                using var httpClient = new HttpClient();
                byte[] imgArray = await httpClient
                                  .GetByteArrayAsync(imgUrl)
                                  .ConfigureAwait(false);

                if (await api.SendMessageAsync(
                        endpoint: context.Endpoint,
                        message: new Message(item.Title.Text + "\r\n")
                        + Message.ByteArrayImage(imgArray)
                        + new Message("\r\n" + item.Links.FirstOrDefault().Uri)
                        ) == null)
                {
                    await api.SendMessageAsync(context.Endpoint, "图片发送失败。");
                }
            }
            else
            {
                await api.SendMessageAsync(context.Endpoint, "没有符合要求的图片。");
            }
        }
示例#9
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            Mode?mode = default(Mode);

            try
            {
                if (!string.IsNullOrWhiteSpace(ModeString))
                {
                    mode = ModeExtensions.Parse(ModeString);
                }
            }
            catch
            {
                // Ignore when the mode string is invalid.
                return;
            }
            Message message;

            if (QQId != default)
            {
                var bindingInfo = await NewbieContext.Bindings.Where(b => b.UserId == QQId).FirstOrDefaultAsync().ConfigureAwait(false);

                if (bindingInfo is null)
                {
                    await api.SendMessageAsync(context.Endpoint, "未绑定 osu! 账号。").ConfigureAwait(false);

                    return;
                }
                var osuId = bindingInfo.OsuId;
                message = await QueryHelper.QueryByUserId(osuId, mode).ConfigureAwait(false);
            }
            else if (!string.IsNullOrEmpty(Name))
            {
                message = await QueryHelper.QueryByUserName(Name, mode).ConfigureAwait(false);
            }
            else
            {
                return;
            }
            object sendResponse = null;

            if (!_memoryCache.TryGetValue(SendingFailureCacheKey, out int t) || t < Threshold)
            {
                sendResponse = await api.SendMessageAsync(context.Endpoint, message).ConfigureAwait(false);
            }
            if (sendResponse is null)
            {
                // 可能会假失败,即消息发出去了,但检测到失败。
                //await api.SendMessageAsync(context.Endpoint, $"检测到发送失败,消息长度为{message.Raw.Length},[调试]将转换成 base64 发送。").ConfigureAwait(false);
                //await api.SendMessageAsync(context.Endpoint, Convert.ToBase64String(Encoding.UTF8.GetBytes(message.Raw))).ConfigureAwait(false);

                // 记录发送失败次数。72小时内失败2次即转图。
                // 不是完全线程安全。
                t = _memoryCache.Set(SendingFailureCacheKey, t + 1, new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(3),
                    Priority          = CacheItemPriority.NeverRemove,
                    SlidingExpiration = TimeSpan.FromDays(1),
                });


                var text = message.Sections[0].Data["text"];
                using var sr = new System.IO.StringReader(text);
                var lines = new List <string>();
                while (sr.ReadLine() is string line)
                {
                    // 分行发送发送失败的消息
                    //await api.SendMessageAsync(context.Endpoint, line).ConfigureAwait(false);

                    lines.Add(line);
                }
                //lines.Add(string.Empty);
                //lines.Add("// 有会 html/css 的帮我弄好看点吗? 斜杠可怜");

                using var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false);

                await page.SetViewportAsync(new ViewPortOptions
                {
                    DeviceScaleFactor = 3,
                    Width             = 360,
                    Height            = 202,
                }).ConfigureAwait(false);

                var style = "font-family: 'Source Han Sans CN', sans-serif;";
                await page.SetContentAsync($@"<div lang=""zh-CN"" style=""{style}"">{string.Join("<br>", lines.Select(HttpUtility.HtmlEncode))}</div>").ConfigureAwait(false);

                var data = await page.ScreenshotDataAsync(new ScreenshotOptions
                {
                    FullPage = true,
                }).ConfigureAwait(false);

                await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false);
            }
        }
示例#10
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            var uid = await EnsureGetBindingIdAsync(context.UserId).ConfigureAwait(false);

            var apiTask = OsuApi.GetUserInfoAsync(uid, Bleatingsheep.Osu.Mode.Standard).ConfigureAwait(false);

            using (var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false))
            {
                await page.SetViewportAsync(new ViewPortOptions
                {
                    DeviceScaleFactor = 2.75,
                    Width             = 1440,
                    Height            = 900,
                }).ConfigureAwait(false);

                await page.GoToAsync($"https://osu.ppy.sh/users/{uid}/osu").ConfigureAwait(false);

                // wait for load complete
                const string waitSelector = @"body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2)";
                await page.WaitForSelectorAsync(waitSelector).ConfigureAwait(false);

                const string bestSelector = "body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.play-detail-list";
                //ElementHandle bpsElement = await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false);

                const string  buttonSelector = "body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.profile-extra-entries__item > button";
                ElementHandle button         = await page.QuerySelectorAsync(buttonSelector).ConfigureAwait(false);

                ElementHandle[]? bpList = default;
                int maxTryTimes = 4;
                while (button != null && maxTryTimes-- != 0)
                {
                    //check bp counts.

                    bpList = await page.QuerySelectorAllAsync(bestSelector + " > div").ConfigureAwait(false);

                    await button.ClickAsync().ConfigureAwait(false);

                    // wait for click complete
                    await page.WaitForSelectorAsync(bestSelector + $" > div:nth-child({bpList.Length})",
                                                    new WaitForSelectorOptions { Timeout = 8000 /*ms*/ }).ConfigureAwait(false);

                    // seems that bp div adding and button availability changing is NOT synchronized
                    // wait for button availability change
                    await page.WaitForTimeoutAsync(500).ConfigureAwait(false);

                    // requery button
                    button = await page.QuerySelectorAsync(buttonSelector).ConfigureAwait(false);
                }

                if (bpList == null)
                {
                    await api.SendMessageAsync(context.Endpoint, "查询失败。").ConfigureAwait(false);

                    return;
                }

                // filter

                /*
                 * bpList = document.querySelectorAll("body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.play-detail-list > div");
                 *
                 * bpList.forEach((element) => { var dateTime = element.querySelector("div.play-detail__group.play-detail__group--top > div.play-detail__detail > div > span.play-detail__time > time").getAttribute("datetime"); if (new Date() - Date.parse(dateTime) > 86400000) element.remove();  })
                 */

                await page.EvaluateExpressionAsync(@"bpList = document.querySelectorAll(""body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.play-detail-list > div"");").ConfigureAwait(false);

                await page.EvaluateExpressionAsync(@"bpList.forEach((element) => { var dateTime = element.querySelector(""div.play-detail__group.play-detail__group--top > div.play-detail__detail > div > span.play-detail__time > time"").getAttribute(""datetime""); if (new Date() - Date.parse(dateTime) > 86400000) element.remove();  })").ConfigureAwait(false);

                // check
                bpList = await page.QuerySelectorAllAsync(bestSelector + " > div").ConfigureAwait(false);

                if (bpList.Length == 0)
                {
                    await api.SendMessageAsync(context.Endpoint, "最近 24 小时没有更新 bp。").ConfigureAwait(false);

                    return;
                }

                //screenshot
                //delete pinned elements
                await(await page.QuerySelectorAsync("body > div.js-pinned-header.hidden-xs.no-print.nav2-header > div.nav2-header__body").ConfigureAwait(false)).EvaluateFunctionAsync(@"(element) => element.remove()").ConfigureAwait(false);
                await(await page.QuerySelectorAsync("body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.hidden-xs.page-extra-tabs.page-extra-tabs--profile-page.js-switchable-mode-page--scrollspy-offset").ConfigureAwait(false)).EvaluateFunctionAsync(@"(element) => element.remove()").ConfigureAwait(false);

                // add extra information
                await page.EvaluateExpressionAsync($@"document.querySelector(""{bestSelector}"").parentElement.parentElement.querySelector(""h3"").textContent += "" (用户名:"" + {JsonConvert.SerializeObject((await apiTask).Item2?.Name ?? "获取失败")} + "" 查询时间:"" + {JsonConvert.SerializeObject(DateTime.Now.ToString("yyyy-MM-dd H:mm)"))}").ConfigureAwait(false);

                //ElementHandle printElement = await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false);
                var printElement =
                    await(await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false))
                    .EvaluateFunctionHandleAsync("(element) => element.parentNode.parentNode").ConfigureAwait(false) as ElementHandle;
                printElement ??= await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false);

                var data = await printElement.ScreenshotDataAsync(new ScreenshotOptions()).ConfigureAwait(false);

                await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false);
            }
        }
示例#11
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            using (var page = await Chrome.OpenNewPageAsync())
            {
                await page.SetViewportAsync(new ViewPortOptions
                {
                    DeviceScaleFactor = 2,
                    Width             = 400,
                    Height            = 3500,
                });

                await page.GoToAsync("https://qieman.com/idx-eval");

                //// Get update time.
                //const string updateDateSelector = "#app > div > div.ant-layout-container > div > div > div.ant-col-xs-24.ant-col-lg-15 > div > div > div.sc-jWBwVP.dtKXxN > div > span.qm-header-note > div > p";
                //var updateDateElement = await page.WaitForSelectorAsync(updateDateSelector);
                //if (updateDateElement != null)
                //{
                //    var property = await updateDateElement.GetPropertyAsync("textContent");
                //    if (property != null)
                //    {
                //        var textContent = (await property.JsonValueAsync()).ToString();
                //        await api.SendMessageAsync(context.Endpoint, textContent);
                //    }
                //    else
                //    {
                //        Logger.Debug($"{nameof(property)} is null.");
                //    }
                //}
                //else
                //{
                //    Logger.Debug($"{nameof(updateDateElement)} is null.");
                //}

                //await Task.Delay(TimeSpan.FromSeconds(3));
                //var xp = await page.QuerySelectorAsync("#app > div > div.ant-layout-container > div > div > div.ant-col-xs-24.ant-col-lg-15 > div > div > div.flex-table__67b31");
                //if (xp != null)
                //    await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(await xp.ScreenshotDataAsync(new ScreenshotOptions
                //    {

                //    })));


                const string  detailSelector = "#app > div.ant-layout-main.ant-layout-main-f > div.ant-layout-container.safe-padding-bottom > div > div > div > div.index__29fc4";
                ElementHandle detailElement  = await page.WaitForSelectorAsync(detailSelector).ConfigureAwait(false);

                // delete advertisement
                const string  adSelector = "#app > div > div.ant-layout-container > div > div > div > div.index__29fc4 > a > img";
                ElementHandle adElement  = await page.QuerySelectorAsync(adSelector).ConfigureAwait(false);

                if (!(adElement is null))
                {
                    await adElement.EvaluateFunctionAsync(@"(element) => { element.parentElement.remove(); }").ConfigureAwait(false);
                }

                var data = await detailElement
                           .ScreenshotDataAsync(new ScreenshotOptions
                {
                    //FullPage = true,
                });

                bool inLoop = true;
                int  retry  = 3;
                do
                {
                    var mesResponse = await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false);

                    inLoop = mesResponse == null;
                } while (inLoop && --retry > 0);
            }
        }
示例#12
0
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            //await api.SendMessageAsync(context.Endpoint, $"[DEBUG] 比较:{_other};模式:{_mode}");

            var id = await DataProvider.EnsureGetBindingIdAsync(context.UserId).ConfigureAwait(false);

            //var browser = GetBrowser();

            byte[] data = null;
            var    mode = Bleatingsheep.Osu.Mode.Standard;

            try
            {
                if (!string.IsNullOrEmpty(_mode))
                {
                    mode = Bleatingsheep.Osu.ModeExtensions.Parse(_mode);
                }
            }
            catch
            {
                await api.SendMessageAsync(context.Endpoint, "模式识别失败,fallback 到 Standard。").ConfigureAwait(false);
            }

            var url = $"http://hydrantweb/pptth/mini/{id}?height=350&mode={(int)mode}";

            if (!string.IsNullOrEmpty(_other))
            {
                var(_, user) = await OsuApi.GetUserInfoAsync(_other, mode);

                if (user == null)
                {
                    ExecutingException.Ensure(false, "对比玩家错误");
                }
                url += $"&compared={user.Id}";
            }
            using (var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false))
            {
                await page.SetViewportAsync(new ViewPortOptions
                {
                    DeviceScaleFactor = 1.15,
                    Width             = 640,
                    Height            = 350,
                }).ConfigureAwait(false);

                await page.GoToAsync(url).ConfigureAwait(false);

                await Task.Delay(0).ConfigureAwait(false);

                data = await page.ScreenshotDataAsync(new ScreenshotOptions
                {
                    FullPage = true,
                    //Type = ScreenshotType.Jpeg,
                    //Quality = 100,
                }).ConfigureAwait(false);
            }

            var stopwatch    = Stopwatch.StartNew();
            var sendResponse = await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false);

            var elapsedTime = stopwatch.ElapsedMilliseconds;
            var failed      = sendResponse is null;

            if (failed)
            {
                await api.SendMessageAsync(context.Endpoint, "图片发送失败(确定)").ConfigureAwait(false);
            }
            (failed ? FailedElapsed : SuccessfulElapsed).Add(elapsedTime);
        }
        public async Task ProcessAsync(MessageContext context, HttpApiClient api)
        {
            var    rendArgs      = _text.Substring("rend ".Length);
            var    rendArgsArray = rendArgs.Split();
            Uri    uri           = default;
            string html          = default;

            if (rendArgsArray[0] != "rss")
            {
                uri = new Uri(rendArgs);
            }
            else
            {
                // RSS
                var rssUrl    = rendArgsArray[1];
                var pageUrl   = rendArgsArray[2];
                var xmlReader = XmlReader.Create(rssUrl);
                var feed      = SyndicationFeed.Load(xmlReader);
                xmlReader.Close();
                var wantedItem = feed.Items.FirstOrDefault(i => string.Equals(i.Links?.FirstOrDefault()?.Uri?.ToString(), pageUrl, StringComparison.OrdinalIgnoreCase));
                if (wantedItem != null)
                {
                    html = wantedItem.Summary.Text;
                }
                else
                {
                    // 没有合理命中的项目。
                    uri = new Uri(pageUrl);
                }
            }

            byte[] data;

            //using (browser)
            using (var page = await Chrome.OpenNewPageAsync())
            {
                await page.SetViewportAsync(new ViewPortOptions
                {
                    DeviceScaleFactor = 1.5,
                    Width             = 360,
                    IsMobile          = true,
                    Height            = 30640,
                    HasTouch          = true,
                });

                if (uri != null)
                {
                    await page.GoToAsync(uri.AbsoluteUri).ConfigureAwait(false);
                }
                else
                {
                    await page.SetContentAsync(html);
                }

                // Wait for 10 seconds to load dynamic contents.
                //await Task.Delay(10000).ConfigureAwait(false);

                await page.SetViewportAsync(new ViewPortOptions
                {
                    DeviceScaleFactor = 1.5,
                    Width             = 360,
                    IsMobile          = true,
                    Height            = 640,
                    HasTouch          = true,
                }).ConfigureAwait(false);

                data = await page.ScreenshotDataAsync(new ScreenshotOptions
                {
                    FullPage = true,
                    Type     = ScreenshotType.Jpeg,
                    Quality  = 100,
                }).ConfigureAwait(false);

                // Save file.
                //const string output_dir = "/root/outputs";
                //var file_name = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ".jpg";
                //var path = Path.Combine(output_dir, file_name);
                //await File.WriteAllBytesAsync(path, data).ConfigureAwait(false);
                //var pictureUri = new Uri($"https://res.bleatingsheep.org/{file_name}");
                //await api.SendMessageAsync(context.Endpoint, pictureUri.AbsoluteUri).ConfigureAwait(false);
            }

            await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data));
        }