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); }
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(); }); }
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 }
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(); }
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 }
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 }
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); } }
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()}"); }
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); }
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 })
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)); }
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); }
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); } }
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); }
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)); }