public async Task <bool?> Handle(MessageEntityEx entity, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (!this.ShouldProcess(entity, context))
            {
                return(null);
            }

            var from  = myClock.GetCurrentInstant().ToDateTimeOffset() - myJitterOffset;
            var polls = await myDB.Set <Poll>()
                        .Where(poll => poll.Time >= from)
                        .Where(poll => poll.Votes.Any(vote => vote.UserId == entity.Message.From.Id))
                        .IncludeRelatedData()
                        .ToListAsync(cancellationToken);

            var builder = new TextBuilder();

            if (polls.Count == 0)
            {
                builder.Append($"No upcoming raids.");
            }
            else
            {
                foreach (var poll in polls.OrderBy(poll => poll.Time))
                {
                    builder.Bold(b =>
                                 b.Code(bb => bb.AppendFormat("{0:t} ", poll.Time)));
                    poll.GetTitle(builder).NewLine();
                }
            }

            var content = builder.ToTextMessageContent(disableWebPreview: true);
            await myBot.SendTextMessageAsync(entity.Message.Chat, content, true, cancellationToken : cancellationToken);

            return(false);
        }
        public async Task <bool?> Handle(MessageEntityEx entity, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (!this.ShouldProcess(entity, context))
            {
                return(null);
            }

            await myTelegramBotClient.SendTextMessageAsync(entity.Message.Chat, "https://telegra.ph/Kak-polzovatsya-Raid-Battles-Bot-07-31", cancellationToken : cancellationToken);

            return(false); // processed, but not pollMessage
        }
예제 #3
0
        public async Task <bool?> Handle(MessageEntityEx data, object context = null, CancellationToken cancellationToken = default)
        {
            if (data.Value.StartsWith("/start", StringComparison.OrdinalIgnoreCase))
            {
                await myBot.SendTextMessageAsync(data.Message.Chat, @"Enter target CP with command `cpXXXX`.", ParseMode.Markdown, cancellationToken : cancellationToken);

                return(true);
            }

            var ignore   = data.Value.StartsWith("/ignore", StringComparison.OrdinalIgnoreCase);
            var unignore = data.Value.StartsWith("/unignore", StringComparison.OrdinalIgnoreCase);

            if (ignore || unignore)
            {
                var ignores = await myContext.Ignore.Where(_ => _.UserId == data.Message.From.Id).ToDictionaryAsync(_ => _.Pokemon, cancellationToken);

                foreach (var segment in data.AfterValue.Split(new [] { ',' }).Select(_ => _.Trim()))
                {
                    if (!short.TryParse(segment, out var number))
                    {
                        if (myPokemons.GetPokemonNumber(segment.ToString()) is { } found)
                        {
                            number = found;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    var exists = ignores.ContainsKey(number);
                    if (ignore && !exists)
                    {
                        var entity = new Ignore {
                            UserId = data.Message.From.Id, Pokemon = number
                        };
                        ignores.Add(number, entity);
                        myContext.Ignore.Add(entity);
                    }
                    else if (unignore && exists)
                    {
                        if (ignores.Remove(number, out var entity))
                        {
                            myContext.Ignore.Remove(entity);
                        }
                    }
                }

                await myContext.SaveChangesAsync(cancellationToken);

                await myBot.SendTextMessageAsync(data.Message.Chat,
                                                 ignores.Values.Aggregate(new StringBuilder("Ignored pokemons: "), (builder, _) => builder.Append($"#{_.Pokemon} {myPokemons.GetPokemonName(_.Pokemon)},")).ToString(), ParseMode.Markdown, cancellationToken : cancellationToken);

                return(true);
            }
    public async Task <bool?> Handle(MessageEntityEx entity, PollMessage?context = default, CancellationToken cancellationToken = default)
    {
        if (this.ShouldProcess(entity, context))
        {
            var text = entity.AfterValue.Trim();
            if (entity.Message != myMessage) // reply mode
            {
                text = myMessage.Text;
            }

            return(await Handle(myMessage, text, context, cancellationToken));
        }

        return(null);
    }
예제 #5
0
        public async Task <bool?> Handle(MessageEntityEx entity, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (!this.ShouldProcess(entity, context))
            {
                return(null);
            }

            var messageChat = entity.Message.Chat;

            var(setContent, setReplyMarkup) = await mySetCallbackQueryHandler.SettingsList(messageChat.Id, cancellationToken);

            await myTelegramBotClient.SendTextMessageAsync(messageChat, setContent,
                                                           disableNotification : true, replyMarkup : setReplyMarkup, cancellationToken : cancellationToken);

            return(false); // processed, but not pollMessage
        }
예제 #6
0
        public async Task <bool?> Handle(MessageEntityEx entity, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (!this.ShouldProcess(entity, context, ctx => ctx.Message.From?.Id is {} userId&& mySuperAdministrators.Contains(userId)))
            {
                return(null);
            }

            var(content, replyMarkup) = await myTimeZoneNotifyService.GetSettingsMessage(entity.Message.Chat, cancellationToken : cancellationToken);

            var message = await myBot.SendTextMessageAsync(entity.Message.Chat, content, disableNotification : true, replyMarkup : replyMarkup, cancellationToken : cancellationToken);

            var(_, updatedReplyMarkup) = await myTimeZoneNotifyService.GetSettingsMessage(message.Chat, message.MessageId, cancellationToken);

            await myBot.EditMessageReplyMarkupAsync(message.Chat, message.MessageId, updatedReplyMarkup, cancellationToken);

            return(false); // processed, but not pollMessage
        }
예제 #7
0
        public async Task <bool?> Handle(MessageEntityEx entity, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (entity.Message.Chat.Type != ChatType.Private)
            {
                return(false);
            }

            var commandText = entity.AfterValue.Trim();

            switch (entity.Command.ToString().ToLowerInvariant())
            {
            case "/ign":
            case "/nick":
            case "/nickname":
                var author = entity.Message.From;
                var player = await myContext.Set <Player>().Where(p => p.UserId == author.Id).FirstOrDefaultAsync(cancellationToken);

                var nickname = commandText.ToString();
                if (string.IsNullOrEmpty(nickname))
                {
                    if (player != null)
                    {
                        myContext.Remove(player);
                    }
                }
                else
                {
                    if (player == null)
                    {
                        player = new Player
                        {
                            UserId = author.Id
                        };
                        myContext.Add(player);
                    }

                    player.Nickname = nickname;
                }
                await myContext.SaveChangesAsync(cancellationToken);

                return(true);

            default:
                return(false);
            }
        }
예제 #8
0
        public async Task <bool?> Handle(MessageEntityEx data, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (!this.ShouldProcess(data, context))
            {
                return(null);
            }

            var player = await myDB.Set <Player>().Get(data.Message.From, cancellationToken);

            var content = new TextBuilder("When someone is asking for Friendship")
                          .ToTextMessageContent();

            var replyMarkup = GetInlineKeyboardMarkup(player);

            await myBot.SendTextMessageAsync(data.Message.Chat.Id, content, replyMarkup : replyMarkup, cancellationToken : cancellationToken);

            return(false); // processed, but not pollMessage
        }
        public async Task <bool?> Handle(MessageEntityEx entity, PollMessage context = default, CancellationToken cancellationToken = default)
        {
            if (!this.ShouldProcess(entity, context))
            {
                return(null);
            }

            var author   = entity.Message.From;
            var settings = await myContext.Set <UserSettings>().Get(author, cancellationToken);

            var content = await GetMessage(settings, cancellationToken);

            var sentMessage = await myBot.SendTextMessageAsync(entity.Message.Chat, content, cancellationToken : cancellationToken,
                                                               replyMarkup : new ReplyKeyboardMarkup(KeyboardButton.WithRequestLocation("Send a location to set up your home place and timezone"))
            {
                ResizeKeyboard = true, OneTimeKeyboard = true
            });

            myCache.GetOrCreate(this[sentMessage.MessageId], _ => true);
            return(false); // processed, but not pollMessage
        }
예제 #10
0
        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);
                        }
                    }
예제 #11
0
 public override bool ShouldProcess(MessageEntityEx data, PollMessage context)
 {
     return(BotCommandHandler.ShouldProcess(this, data, context));
 }
예제 #12
0
        public async Task <bool?> Handle(MessageEntityEx entity, PollMessage pollMessage, CancellationToken cancellationToken = default)
        {
            var commandText = entity.AfterValue.Trim();

            switch (entity.Command.ToString().ToLowerInvariant())
            {
            case "/new":
                var title = commandText;
                if (StringSegment.IsNullOrEmpty(title))
                {
                    return(false);
                }

                pollMessage.Poll = new Poll(myMessage)
                {
                    Title = title.Value
                };
                return(true);

            case "/poll"  when PollEx.TryGetPollId(commandText, out var pollId, out _):
            case "/start" when PollEx.TryGetPollId(commandText, out pollId, out _):

                var existingPoll = await myContext
                                   .Set <Poll>()
                                   .Where(_ => _.Id == pollId)
                                   .IncludeRelatedData()
                                   .FirstOrDefaultAsync(cancellationToken);

                if (existingPoll == null)
                {
                    return(false);
                }

                pollMessage.Poll = existingPoll;
                return(true);

            case "/set":

                var(setContent, setReplyMarkup) = await mySetCallbackQueryHandler.SettingsList(myMessage.Chat.Id, cancellationToken);

                await myTelegramBotClient.SendTextMessageAsync(myMessage.Chat, setContent.MessageText, setContent.ParseMode, setContent.DisableWebPagePreview,
                                                               disableNotification : true, replyMarkup : setReplyMarkup, cancellationToken : cancellationToken);

                return(false); // processed, but not pollMessage

            case "/help" when myMessage.Chat.Type == ChatType.Private:
                await myTelegramBotClient.SendTextMessageAsync(myMessage.Chat, "http://telegra.ph/Raid-Battles-Bot-Help-02-18", cancellationToken : cancellationToken);

                return(false); // processed, but not pollMessage

            // deep linking to gym
            case "/start" when commandText.StartsWith(GeneralInlineQueryHandler.SwitchToGymParameter, StringComparison.Ordinal):
                var query = commandText.Substring(GeneralInlineQueryHandler.SwitchToGymParameter.Length);

                var pollTitle = new StringBuilder("Poll creation");
                if (int.TryParse(query, out int gymPollId))
                {
                    pollTitle
                    .NewLine()
                    .Bold((builder, m) => builder.Sanitize(myRaidService.GetTemporaryPoll(gymPollId)?.Title, m));
                }

                var content = pollTitle.ToTextMessageContent();
                await myTelegramBotClient.SendTextMessageAsync(myMessage.Chat, content.MessageText, content.ParseMode, content.DisableWebPagePreview, disableNotification : true,
                                                               replyMarkup : new InlineKeyboardMarkup(InlineKeyboardButton.WithSwitchInlineQueryCurrentChat("Choose a Gym", $"{GymInlineQueryHandler.PREFIX}{query} ")), cancellationToken : cancellationToken);

                return(false);

            case "/p" when int.TryParse(commandText, out var pollId):
                var poll = await myContext
                           .Set <Poll>()
                           .Where(_ => _.Id == pollId)
                           .IncludeRelatedData()
                           .FirstOrDefaultAsync(cancellationToken);

                if (poll == null)
                {
                    return(false);
                }

                var voters = poll.Votes.ToDictionary(vote => vote.UserId, vote => vote.User);
                var users  = poll.Messages
                             .Where(message => message.UserId != null)
                             .Select(message => message.UserId.Value)
                             .Distinct()
                             .ToList();
                var unknownUsers = users.Where(u => !voters.ContainsKey(u)).ToList();
                var data         = await myContext
                                   .Set <Vote>()
                                   .Where(v => unknownUsers.Contains(v.UserId))
                                   .GroupBy(v => v.UserId)
                                   .Select(vv => vv.OrderByDescending(vote => vote.Modified).First())
                                   .ToListAsync(cancellationToken);

                var allVoters = voters.Values.Concat(data.Select(d => d.User))
                                .ToDictionary(u => u.Id, u => u);
                var info = users
                           .Select(u => allVoters.TryGetValue(u, out var user) ?
                                   user : new User {
                    Id = u, FirstName = u.ToString()
                })
                           .Aggregate(
                    poll.GetDescription(myUrlHelper).NewLine().NewLine(),
                    (builder, user) => builder.Append(user.GetLink()).NewLine())
                           .ToTextMessageContent(disableWebPreview: true);

                await myTelegramBotClient.SendTextMessageAsync(myMessage.Chat, info.MessageText, info.ParseMode, info.DisableWebPagePreview, disableNotification : true,
                                                               replyToMessageId : myMessage.MessageId, cancellationToken : cancellationToken);

                return(false);
            }

            return(null);
        }