public async Task <bool?> Handle(MessageEntityEx entity, PollMessage pollMessage, CancellationToken cancellationToken = default) { var url = myGetUrl(entity); if (StringSegment.IsNullOrEmpty(url) || !url.StartsWith("http", StringComparison.Ordinal)) { return(false); } using (var httpClient = myHttpClientFactory.CreateClient()) { var poketrackRequest = new HttpRequestMessage(HttpMethod.Head, url.ToString()); if (InfoGymBotHelper.IsAppropriateUrl(poketrackRequest.RequestUri)) { poketrackRequest.Method = HttpMethod.Get; } var requestUri = poketrackRequest.RequestUri; HttpContent poketrackResponseContent = null; if (!myBotConfiguration?.SkipDomains.Contains(requestUri.Host, StringComparer.OrdinalIgnoreCase) ?? true) { var poketrackResponse = await httpClient.SendAsync(poketrackRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken); poketrackResponseContent = poketrackResponse.Content; requestUri = poketrackResponse.RequestMessage.RequestUri; } var query = QueryHelpers.ParseQuery(requestUri.Query); bool ParseCoordinate(string str, out decimal coordinate) => decimal.TryParse(str, NumberStyles.Currency, CultureInfo.InvariantCulture, out coordinate); bool GetGoogleLocation(Uri uri, string prefix, int position, out decimal lt, out decimal ln) { lt = 0; ln = 0; return(uri.LocalPath.StartsWith(prefix) && uri.Segments.ElementAtOrDefault(position) is var location && location?.Split(new[] { '@', ',', '/' }, StringSplitOptions.RemoveEmptyEntries) is var locationParts && locationParts?.Length > 1 && ParseCoordinate(locationParts[0], out lt) && ParseCoordinate(locationParts[1], out ln)); } if ((query.TryGetValue("lon", out var lonParameter) && ParseCoordinate(lonParameter, out var lon) && query.TryGetValue("lat", out var latParameter) && ParseCoordinate(latParameter, out var lat)) || (GetGoogleLocation(requestUri, "/maps/search", 3, out lat, out lon) || GetGoogleLocation(requestUri, "/maps/place", 4, out lat, out lon))) { var title = new StringBuilder(); var description = new StringBuilder(); var raid = new Raid { Lon = lon, Lat = lat }; var messageDate = entity.Message.GetMessageDate(myTimeZoneInfo); raid.StartTime = messageDate.ToDateTimeOffset(); var messageText = entity.Message.Text; var lines = messageText.Split(Environment.NewLine.ToCharArray(), 2); var firstLine = lines[0].Trim(); if (InfoGymBotHelper.IsAppropriateUrl(requestUri)) { try { if (poketrackResponseContent is HttpContent content && await content.ReadAsStringAsync() is var poketrackResponseStringContent && ourRaidInfoBotGymDetector.Match(poketrackResponseStringContent) is var raidInfoBotGymMatch && raidInfoBotGymMatch.Success) { raid.PossibleGym = raidInfoBotGymMatch.Value; } } catch (Exception e) { myTelemetryClient.TrackExceptionEx(e, pollMessage.GetTrackingProperties()); } if (query.TryGetValue("b", out var boss)) { var movesString = lines.ElementAtOrDefault(1); if (movesString?.IndexOf("{подробнее}", StringComparison.Ordinal) is int tail && tail >= 0) { movesString = movesString.Remove(tail); } else if (movesString?.IndexOf("📌", StringComparison.Ordinal) is int tail2 && tail2 >= 0) { movesString = movesString.Remove(tail2); } raid.ParseRaidInfo(myPokemons, boss.ToString(), movesString); if (query.TryGetValue("t", out var time) && messageDate.ParseTime(time, out var dateTime)) { raid.RaidBossEndTime = dateTime; } else if (query.TryGetValue("tb", out time) && messageDate.ParseTime(time, out dateTime)) { raid.EndTime = dateTime; } } else { title.Append(firstLine); } }