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);
        }
Beispiel #2
0
 private async void EndPoll()
 {
     await PollMessage.ModifyAsync(msg =>
     {
         msg.Embed = new EmbedBuilder()
                     .WithTitle($"Poll now over! The people have voted that the answer to \"{PollQuestion}\" is {GetAnswer()}!")
                     .Build();
     });
 }
Beispiel #3
0
        internal async Task AddAllReactions()
        {
            List <Emoji> emojis = new List <Emoji>();

            foreach (PollOption po in PollOptions)
            {
                emojis.Add(po.React);
            }
            await PollMessage.AddReactionsAsync(emojis.ToArray());
        }
        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
        }
Beispiel #5
0
        private async void SendAndManagePoll(IMessageChannel channel)
        {
            string pollString = PollChannel.Name == "announcements" ? "@everyone" : "";

            PollMessage = await channel.SendMessageAsync(pollString, embed : PollEmbed);

            await PollMessage.AddReactionAsync(Check);

            await PollMessage.AddReactionAsync(CrossOut);

            PollTimer.Start();
        }
Beispiel #6
0
        public PollClosedMessage(PollMessage message)
        {
            FromUser = SystemChatMessage.SystemUser;
            Poll     = message;
            Winners  = new List <PollChoice>();
            int maxVotes = Poll.Choices.Max(c => c.Votes.Count);

            if (maxVotes > 0)
            {
                Winners.AddRange(Poll.Choices.Where(c => c.Votes.Count == maxVotes));
            }
        }
        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
        }
Beispiel #8
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
        }
Beispiel #9
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);
            }
        }
Beispiel #10
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
        }
        public async Task <(string, bool, string)> Handle(CallbackQuery data, object context = default, CancellationToken cancellationToken = default)
        {
            var callback = data.Data.Split(':');

            if (callback[0] != "clone")
            {
                return(null, false, null);
            }

            if (!int.TryParse(callback.ElementAtOrDefault(1) ?? "", NumberStyles.Integer, CultureInfo.InvariantCulture, out var pollId))
            {
                return("Poll is publishing. Try later.", true, null);
            }

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

            if (poll == null)
            {
                return("Poll is not found", true, null);
            }

            var pollMessage = new PollMessage
            {
                ChatId           = data.From.Id,
                ChatType         = ChatType.Private,
                UserId           = data.From.Id,
                InlineMesssageId = data.InlineMessageId,
                Poll             = poll
            };
            await myRaidService.AddPollMessage(pollMessage, myUrlHelper, cancellationToken);

            var botUser = await myBot.GetMeAsync(cancellationToken);

            return(null, false, $"https://t.me/{botUser.Username}?start={pollMessage.GetExtendedPollId()}");
        }
Beispiel #13
0
        internal async Task Update()
        {
            try
            {
                await PollMessage.ModifyAsync(x =>
                {
                    x.Content = "";
                    x.Embed   = CreatePollEmbed();
                });
            }
            catch (Discord.Net.HttpException e)
            {
                Console.WriteLine($"EXCEPTION: {(e.DiscordCode.HasValue ? e.DiscordCode : null)} - [{e.HResult}] {e.Reason}");
                await LogWriter.WriteLogFile($"EXCEPTION: {(e.DiscordCode.HasValue ? e.DiscordCode : null)} - [{e.HResult}] {e.Reason}");

                Console.WriteLine($"Request: {JsonConvert.SerializeObject(e.Request.Options)}");
                await LogWriter.WriteLogFile($"Request: {JsonConvert.SerializeObject(e.Request.Options)}");

                Console.WriteLine($"{e.StackTrace}");
                await LogWriter.WriteLogFile($"{e.StackTrace}");
            }
        }
        public async Task <bool?> Handle(ChosenInlineResult data, object context = default, CancellationToken cancellationToken = default)
        {
            var resultParts = data.ResultId.Split(':');

            switch (resultParts[0])
            {
            case PollEx.InlineIdPrefix:
                if (!PollEx.TryGetPollId(resultParts.ElementAtOrDefault(1), out var pollId, out var format))
                {
                    return(null);
                }
                var message = new PollMessage(data)
                {
                    BotId = myBot.BotId, PollId = pollId
                };
                if (Enum.TryParse <PollMode>(resultParts.ElementAtOrDefault(3), out var pollMode))
                {
                    message.PollMode = pollMode;
                }
                var pollMessage = await myRaidService.GetOrCreatePollAndMessage(message, myUrlHelper, format, cancellationToken);

                if (pollMessage != null)
                {
                    if (pollMessage.Poll is { } poll&&  (poll.Portal?.Guid ?? poll.PortalId) is { } guid)
                    {
                        await myPoGoToolsClient.UpdateWayspot(guid, poll.ExRaidGym?Wayspot.ExRaidGym : Wayspot.Gym, cancellationToken);
                    }

                    return(true);
                }

                return(false);
            }

            return(null);
        }
Beispiel #15
0
        public async Task Execute(CancellationToken cancellationToken)
        {
            var nowWithLeadTime = myClock.GetCurrentInstant().ToDateTimeOffset() + myNotificationLeadTime;
            var previous        = nowWithLeadTime - CheckPeriod - ErrorOffset;
            var polls           = await myDB.Set <Poll>()
                                  .Where(poll => poll.Time > previous && poll.Time <= nowWithLeadTime)
                                  .IncludeRelatedData()
                                  .Include(poll => poll.Notifications)
                                  .ToListAsync(cancellationToken);

            foreach (var poll in polls)
            {
                using var notificationOperation = myTelemetryClient.StartOperation(
                          new DependencyTelemetry(GetType().Name, null, "PollNotification", poll.Id.ToString()));
                var pollMode        = poll.AllowedVotes?.HasFlag(VoteEnum.Invitation) ?? false ? PollMode.DefaultWithInvitation : default;
                var alreadyNotified = poll.Notifications.Where(notification => notification.Type == NotificationType.PollTime).Select(notification => notification.ChatId).ToHashSet();
                foreach (var pollVote in poll.Votes)
                {
                    var botId  = pollVote.BotId;
                    var userId = pollVote.UserId;
                    if (!(pollVote.Team?.HasAnyFlags(VoteEnum.Notify) ?? false))
                    {
                        continue;
                    }
                    if (alreadyNotified.Contains(userId))
                    {
                        continue;
                    }
                    try
                    {
                        var pollMessage = new PollMessage
                        {
                            BotId  = botId,
                            UserId = userId,
                            Chat   = new Chat {
                                Id = userId, Type = ChatType.Private
                            },
                            Poll     = poll,
                            PollId   = poll.Id,
                            PollMode = pollMode
                        };
                        var notificationMessage = await myRaidService.GetOrCreatePollAndMessage(pollMessage, null, poll.AllowedVotes, cancellationToken);

                        var notification = new Notification
                        {
                            PollId    = poll.Id,
                            BotId     = pollMessage.BotId,
                            ChatId    = notificationMessage.Chat.Id,
                            MessageId = notificationMessage.MessageId,
                            DateTime  = notificationMessage.Modified,
                            Type      = NotificationType.PollTime
                        };
                        poll.Notifications.Add(notification);
                        myTelemetryClient.TrackEvent("Notification", new Dictionary <string, string?>
                        {
                            { nameof(notificationMessage.UserId), notificationMessage.UserId?.ToString() },
                            { nameof(notificationMessage.PollId), notificationMessage.PollId.ToString() },
                            { nameof(notificationMessage.BotId), notificationMessage.BotId?.ToString() },
                            { nameof(notificationMessage.ChatId), notificationMessage.ChatId?.ToString() },
                            { nameof(notificationMessage.MessageId), notificationMessage.MessageId?.ToString() }
                        });
                    }
                    catch (Exception ex)
                    {
                        if (ex is ApiRequestException {
                            ErrorCode: 403
                        })
Beispiel #16
0
        public async Task <PollMessage> GetOrCreatePollAndMessage(PollMessage pollMessage, IUrlHelper urlHelper, VoteEnum?format = null, CancellationToken cancellationToken = default)
        {
            bool exRaidGym = false;
            var  pollId    = pollMessage.PollId;

            if (pollId < 0)
            {
                pollId    = pollMessage.PollId = -pollId;
                exRaidGym = true;
            }
            var poll = await myContext
                       .Set <Poll>()
                       .Where(_ => _.Id == pollId)
                       .IncludeRelatedData()
                       .FirstOrDefaultAsync(cancellationToken);

            if (poll != null)
            {
                var existingMessage = poll.Messages.FirstOrDefault(_ => _.InlineMesssageId == pollMessage.InlineMesssageId && _.ChatId == pollMessage.ChatId && _.MesssageId == pollMessage.MesssageId);
                if (existingMessage != null)
                {
                    return(existingMessage);
                }

                pollMessage.Poll = poll;
                return(await AddPollMessage(pollMessage, urlHelper, cancellationToken));
            }

            var pollData = GetTemporaryPoll(pollId);

            if (pollData == null)
            {
                return(null);
            }

            pollMessage.Poll = new Poll
            {
                Id           = pollId,
                Title        = pollData.Title,
                AllowedVotes = format,
                Owner        = pollData.Owner,
                Portal       = pollData.Portal,
                ExRaidGym    = exRaidGym,
                Votes        = new List <Vote>()
            };
            myContext.Set <Poll>().Attach(pollMessage.Poll).State = EntityState.Added;
            if (pollData.Portal is Portal portal)
            {
                var portalSet      = myContext.Set <Portal>();
                var existingPortal = await portalSet.AsTracking().FirstOrDefaultAsync(p => p.Guid == portal.Guid, cancellationToken);

                if (existingPortal == null)
                {
                    portalSet.Attach(portal).State = EntityState.Added;
                }
                else
                {
                    existingPortal.Guid            = portal.Guid;
                    existingPortal.Name            = portal.Name;
                    existingPortal.Address         = portal.Address;
                    existingPortal.Image           = portal.Image;
                    existingPortal.Latitude        = portal.Latitude;
                    existingPortal.Longitude       = portal.Longitude;
                    portalSet.Attach(portal).State = EntityState.Modified;
                }
            }

            return(await AddPollMessage(pollMessage, urlHelper, cancellationToken, withLog : true));
        }
Beispiel #17
0
        public async Task <PollMessage> AddPollMessage([CanBeNull] PollMessage message, IUrlHelper urlHelper, CancellationToken cancellationToken = default, bool withLog = false)
        {
            if (message?.Poll == null)
            {
                return(message);
            }

            message.Poll.AllowedVotes =
                message.Poll.AllowedVotes ?? await myContext.Set <Settings>().GetFormat(message.UserId, cancellationToken);

            var raidUpdated    = false;
            var eggRaidUpdated = false;

            if (message.Poll?.Raid is Raid raid)
            {
                if (raid.Id == 0)
                {
                    var sameRaids = myContext
                                    .Set <Raid>()
                                    .Where(_ => _.Lon == raid.Lon && _.Lat == raid.Lat);
                    var existingRaid = await sameRaids
                                       .Where(_ => _.RaidBossLevel == raid.RaidBossLevel && _.Pokemon == raid.Pokemon && _.EndTime == raid.EndTime)
                                       .Include(_ => _.EggRaid)
                                       .IncludeRelatedData()
                                       .FirstOrDefaultAsync(cancellationToken);

                    if (existingRaid != null)
                    {
                        if (((existingRaid.Gym ?? existingRaid.PossibleGym) == null) && ((raid.Gym ?? raid.PossibleGym) != null))
                        {
                            existingRaid.PossibleGym = raid.Gym ?? raid.PossibleGym;
                            raidUpdated = true;
                        }

                        if (string.IsNullOrEmpty(message.Poll.Title))
                        {
                            // use existing poll if have rights for any prev message
                            foreach (var existingRaidPoll in existingRaid.Polls)
                            {
                                foreach (var existingRaidPollMessage in existingRaidPoll.Messages)
                                {
                                    if (await myChatInfo.CanReadPoll(existingRaidPollMessage.ChatId ?? existingRaidPollMessage.Poll.Owner, message.UserId ?? message.ChatId, cancellationToken))
                                    {
                                        if ((existingRaidPoll.Votes?.Count ?? 0) >= (message.Poll.Messages?.Count ?? 0))
                                        {
                                            message.Poll = existingRaidPoll;
                                            break;
                                        }
                                    }
                                }

                                if (message.Poll == existingRaidPoll)
                                {
                                    break;
                                }
                            }
                        }

                        raid = message.Poll.Raid = existingRaid;
                    }

                    if ((raid.Pokemon != null) && (raid.EggRaid == null)) // check for egg raid
                    {
                        var eggRaid = await sameRaids
                                      .Where(_ => _.Pokemon == null && _.RaidBossEndTime == raid.RaidBossEndTime)
                                      .IncludeRelatedData()
                                      .DecompileAsync()
                                      .FirstOrDefaultAsync(cancellationToken);

                        if ((eggRaid != null) && (raid.Id != eggRaid.Id))
                        {
                            var eggRaidPolls = eggRaid.Polls = eggRaid.Polls ?? new List <Poll>(0);
                            var raidPolls    = raid.Polls = raid.Polls ?? new List <Poll>(eggRaidPolls.Count);
                            // on post egg raid creation update all existing polls to new raid
                            foreach (var eggRaidPoll in new List <Poll>(eggRaidPolls))
                            {
                                eggRaidPolls.Remove(eggRaidPoll);
                                raidPolls.Add(eggRaidPoll);
                                eggRaidPoll.Raid = raid;
                                raidUpdated      = true;

                                if (!string.IsNullOrEmpty(message.Poll.Title))
                                {
                                    continue;
                                }

                                // use existing poll if have rights for any prev message
                                foreach (var eggRaidPollMessage in eggRaidPoll.Messages)
                                {
                                    if (await myChatInfo.CanReadPoll(eggRaidPollMessage.ChatId ?? eggRaidPollMessage.Poll.Owner, message.UserId ?? message.ChatId, cancellationToken))
                                    {
                                        if ((eggRaidPoll.Votes?.Count ?? 0) >= (message.Poll.Messages?.Count ?? 0))
                                        {
                                            message.Poll = eggRaidPoll;
                                            break;
                                        }
                                    }
                                }
                            }
                            message.Poll.Raid = raid;
                            raid.EggRaid      = eggRaid;
                            eggRaidUpdated    = true;
                        }
                    }
                }
            }

            var messageEntity = myContext.Set <PollMessage>().Attach(message);
            await myContext.SaveChangesAsync(cancellationToken);

            // update current raid poll messages if changed
            if (raidUpdated && message.Poll.Raid is Raid raidToUpdate)
            {
                foreach (var poll in raidToUpdate.Polls ?? Enumerable.Empty <Poll>())
                {
                    await UpdatePoll(poll, urlHelper, cancellationToken);
                }
            }

            // update egg raid poll messages if any
            if (eggRaidUpdated && message.Poll.Raid?.EggRaid is Raid eggRaidToUpdate)
            {
                foreach (var poll in eggRaidToUpdate.Polls ?? Enumerable.Empty <Poll>())
                {
                    await UpdatePoll(poll, urlHelper, cancellationToken);
                }
            }

            var content = message.Poll.GetMessageText(urlHelper, disableWebPreview: message.Poll.DisableWebPreview());

            if (message.Chat is Chat chat)
            {
                var postedMessage = await myBot.SendTextMessageAsync(chat, content.MessageText, content.ParseMode, content.DisableWebPagePreview,
                                                                     replyMarkup : await message.GetReplyMarkup(myChatInfo, cancellationToken), disableNotification : true,

                                                                     cancellationToken : cancellationToken);

                message.Chat       = postedMessage.Chat;
                message.MesssageId = postedMessage.MessageId;
            }
            else if (message.InlineMesssageId is string inlineMessageId)
            {
                //await myBot.EditInlineMessageTextAsync(inlineMessageId, messageText, RaidEx.ParseMode, disableWebPagePreview: message.Poll.GetRaidId() == null,
                //  replyMarkup: await message.GetReplyMarkup(myChatInfo, cancellationToken), cancellationToken: cancellationToken);
            }

            await myContext.SaveChangesAsync(cancellationToken);

            // log message
            if (withLog && myLogChat != null)
            {
                await AddPollMessage(new PollMessage { ChatId = myLogChat, Poll = message.Poll }, urlHelper, cancellationToken);
            }

            return(message);
        }
Beispiel #18
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);
                        }
                    }
Beispiel #19
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);
        }
Beispiel #20
0
        public async Task <PollMessage> GetOrCreatePollAndMessage(PollMessage pollMessage, IUrlHelper urlHelper, VoteEnum?format = null, CancellationToken cancellationToken = default)
        {
            bool exRaidGym = false;
            var  pollId    = pollMessage.PollId;

            if (pollId < 0)
            {
                pollId    = pollMessage.PollId = -pollId;
                exRaidGym = true;
            }
            var poll = pollMessage.Poll ?? await myContext
                       .Set <Poll>()
                       .Where(_ => _.Id == pollId)
                       .IncludeRelatedData()
                       .Include(poll => poll.Notifications)
                       .FirstOrDefaultAsync(cancellationToken);

            if (poll != null)
            {
                var existingMessage = poll.Messages.FirstOrDefault(_ => _.InlineMessageId == pollMessage.InlineMessageId && _.ChatId == pollMessage.ChatId && _.MessageId == pollMessage.MessageId);
                if (existingMessage != null)
                {
                    return(existingMessage);
                }

                pollMessage.Poll = poll;
                return(await AddPollMessage(pollMessage, urlHelper, cancellationToken));
            }

            var pollData = GetTemporaryPoll(pollId);

            if (pollData == null)
            {
                return(null);
            }

            pollMessage.Poll = new Poll
            {
                Id           = pollId,
                Title        = pollData.Title,
                AllowedVotes = format,
                Owner        = pollData.Owner,
                Portal       = pollData.Portal,
                ExRaidGym    = exRaidGym,
                Time         = pollData.Time,
                TimeZoneId   = pollData.TimeZoneId,
                Votes        = pollData.Votes,
                Limits       = pollData.Limits
            };
            if (pollMessage.UserId is { } userId)
            {
                pollMessage.Poll.InitImplicitVotes(GetCachedUser(userId), pollMessage.BotId);
            }

            // MUST be set before portal
            myContext.Set <Poll>().Attach(pollMessage.Poll).State = EntityState.Added;

            if (pollData.Portal is { } portal)
            {
                var portalSet = myContext.Set <Portal>();
                // always check remote
                var existingPortal = await portalSet.AsNoTracking().FirstOrDefaultAsync(p => p.Guid == portal.Guid, cancellationToken);

                if (existingPortal == null)
                {
                    portalSet.Attach(portal).State = EntityState.Added;
                }
                else
                {
                    myContext.Entry(existingPortal).SetNotNullProperties(portal);
                    myContext.Entry(portal).SetNotNullProperties(existingPortal);
                }
            }

            return(await AddPollMessage(pollMessage, urlHelper, cancellationToken, withLog : true));
        }