Skip to content

Commit cc832fe

Browse files
committed
Fetch user fresh, rather than using cache, when validating
1 parent 23002e9 commit cc832fe

5 files changed

Lines changed: 56 additions & 33 deletions

File tree

Present/Commands/GiveawayCommand.Redraw.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,26 @@ public async Task RedrawAsync(InteractionContext context,
4141
{
4242
foreach (string keepId in keepIds.Split((char[]?) null, StringSplitOptions.RemoveEmptyEntries))
4343
{
44-
if (ulong.TryParse(keepId, out ulong userId) &&
45-
_giveawayService.ValidateUser(userId, guild, out DiscordMember? member))
46-
keep.Add(member);
47-
else
44+
if (!ulong.TryParse(keepId, out ulong userId))
45+
{
4846
invalidKeepIds.Add(keepId);
47+
continue;
48+
}
49+
50+
DiscordMember? member = await _giveawayService.ValidateUserAsync(userId, giveaway).ConfigureAwait(false);
51+
if (member is null) invalidKeepIds.Add(keepId);
52+
else keep.Add(member);
4953
}
5054
}
5155

52-
IReadOnlyList<DiscordMember> winners = _giveawayService.SelectWinners(giveaway, keep);
56+
IReadOnlyList<DiscordMember> winners = await _giveawayService.SelectWinnersAsync(giveaway, keep).ConfigureAwait(false);
5357
await _giveawayService.UpdateWinnersAsync(giveaway, winners).ConfigureAwait(false);
5458

5559
await _giveawayService.EditGiveawayAsync(giveaway).ConfigureAwait(false);
5660
await _giveawayService.UpdateGiveawayLogMessageAsync(giveaway).ConfigureAwait(false);
5761
await _giveawayService.UpdateGiveawayPublicMessageAsync(giveaway).ConfigureAwait(false);
5862

59-
embed = _giveawayService.CreateGiveawayInformationEmbed(giveaway);
63+
embed = await _giveawayService.CreateGiveawayInformationEmbedAsync(giveaway).ConfigureAwait(false);
6064
embed.WithColor(DiscordColor.Green);
6165
embed.WithTitle(EmbedStrings.GiveawayEdited_Title);
6266

Present/Commands/GiveawayCommand.SetWinners.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public async Task SetWinnersAsync(InteractionContext context,
4747
await _giveawayService.UpdateGiveawayLogMessageAsync(giveaway).ConfigureAwait(false);
4848
await _giveawayService.UpdateGiveawayPublicMessageAsync(giveaway).ConfigureAwait(false);
4949

50-
embed = _giveawayService.CreateGiveawayInformationEmbed(giveaway);
50+
embed = await _giveawayService.CreateGiveawayInformationEmbedAsync(giveaway).ConfigureAwait(false);
5151
embed.WithColor(DiscordColor.Green);
5252
embed.WithTitle(EmbedStrings.GiveawayEdited_Title);
5353
await context.CreateResponseAsync(embed).ConfigureAwait(false);

Present/Commands/GiveawayCommand.View.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task ViewAsync(InteractionContext context,
2626
return;
2727
}
2828

29-
embed = _giveawayService.CreateGiveawayInformationEmbed(giveaway);
29+
embed = await _giveawayService.CreateGiveawayInformationEmbedAsync(giveaway).ConfigureAwait(false);
3030
embed.WithTitle(EmbedStrings.GiveawayInformation);
3131

3232
await context.CreateResponseAsync(embed).ConfigureAwait(false);

Present/Services/ActiveGiveawayService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private async Task HandleExpiredGiveawayAsync(Giveaway giveaway)
147147
giveaway.EndHandled = true;
148148
RemoveActiveGiveaway(giveaway);
149149

150-
IReadOnlyList<DiscordMember> winners = _giveawayService.SelectWinners(giveaway);
150+
IReadOnlyList<DiscordMember> winners = await _giveawayService.SelectWinnersAsync(giveaway).ConfigureAwait(false);
151151
Logger.Info($"Selected {"winner".ToQuantity(winners.Count)} for giveaway {giveaway.Id} ({giveaway.Title})");
152152
foreach (DiscordMember winner in winners)
153153
Logger.Info(winner);

Present/Services/GiveawayService.cs

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using Microsoft.Extensions.Hosting;
1212
using NLog;
1313
using SmartFormat;
14-
using X10D.Collections;
1514
using X10D.Core;
1615
using X10D.DSharpPlus;
1716

@@ -169,7 +168,7 @@ public async Task<Giveaway> CreateGiveawayAsync(GiveawayCreationOptions options)
169168
/// <param name="giveaway">The giveaway whose information to fetch.</param>
170169
/// <returns>A <see cref="DiscordEmbedBuilder" />, populated with information from <paramref name="giveaway" />.</returns>
171170
/// <exception cref="ArgumentNullException"><paramref name="giveaway" /> is <see langword="null" />.</exception>
172-
public DiscordEmbedBuilder CreateGiveawayInformationEmbed(Giveaway giveaway)
171+
public async Task<DiscordEmbedBuilder> CreateGiveawayInformationEmbedAsync(Giveaway giveaway)
173172
{
174173
ArgumentNullException.ThrowIfNull(giveaway);
175174

@@ -188,7 +187,14 @@ public DiscordEmbedBuilder CreateGiveawayInformationEmbed(Giveaway giveaway)
188187
var jumpLink = new Uri($"https://discord.com/channels/{giveaway.GuildId}/{giveaway.ChannelId}/{giveaway.MessageId}");
189188
string conjugatedEnd = giveaway.EndTime < DateTimeOffset.UtcNow ? EmbedStrings.Ended : EmbedStrings.Ends;
190189
var entrantsCount = giveaway.Entrants.Count.ToString("N0");
191-
var excludedEntrantsCount = giveaway.Entrants.CountWhereNot(e => ValidateUser(e, guild, out _)).ToString("N0");
190+
var excludedEntrantsCount = 0;
191+
foreach (ulong entrantId in giveaway.Entrants)
192+
{
193+
DiscordMember? member = await ValidateUserAsync(entrantId, giveaway).ConfigureAwait(false);
194+
if (member is null) excludedEntrantsCount++;
195+
}
196+
197+
var excludedEntrants = excludedEntrantsCount.ToString("N0");
192198

193199
embed.AddField(EmbedStrings.Title, giveaway.Title);
194200
embed.AddField(EmbedStrings.Description, description);
@@ -199,7 +205,7 @@ public DiscordEmbedBuilder CreateGiveawayInformationEmbed(Giveaway giveaway)
199205
embed.AddField(conjugatedEnd, Formatter.Timestamp(giveaway.EndTime), true);
200206
embed.AddField(EmbedStrings.Creator, MentionUtility.MentionUser(giveaway.CreatorId), true);
201207
embed.AddField(EmbedStrings.Entrants, entrantsCount, true);
202-
embed.AddField(EmbedStrings.ExcludedEntrants, excludedEntrantsCount, true);
208+
embed.AddField(EmbedStrings.ExcludedEntrants, excludedEntrants, true);
203209
embed.AddFieldIf(giveaway.ImageUri is not null, "Image", () => Formatter.MaskedUrl("View", giveaway.ImageUri), true);
204210

205211
List<ulong> winnerIds = giveaway.WinnerIds;
@@ -218,11 +224,11 @@ public DiscordEmbedBuilder CreateGiveawayInformationEmbed(Giveaway giveaway)
218224
/// <param name="giveaway">The giveaway whose log embed to return.</param>
219225
/// <returns>The log embed.</returns>
220226
/// <exception cref="ArgumentNullException"><paramref name="giveaway" /> is <see langword="null" />.</exception>
221-
public DiscordEmbed CreateGiveawayLogEmbed(Giveaway giveaway)
227+
public async Task<DiscordEmbed> CreateGiveawayLogEmbedAsync(Giveaway giveaway)
222228
{
223229
ArgumentNullException.ThrowIfNull(giveaway);
224230

225-
DiscordEmbedBuilder embed = CreateGiveawayInformationEmbed(giveaway);
231+
DiscordEmbedBuilder embed = await CreateGiveawayInformationEmbedAsync(giveaway).ConfigureAwait(false);
226232
embed.WithTitle(EmbedStrings.GiveawayCreated_Title_NoEmoji);
227233
embed.WithColor(DiscordColor.Green);
228234
return embed;
@@ -425,7 +431,7 @@ public async Task LogGiveawayCreationAsync(Giveaway giveaway)
425431
return;
426432
}
427433

428-
DiscordEmbedBuilder embed = CreateGiveawayInformationEmbed(giveaway);
434+
DiscordEmbedBuilder embed = await CreateGiveawayInformationEmbedAsync(giveaway).ConfigureAwait(false);
429435
embed.WithTitle(EmbedStrings.GiveawayCreated_Title_NoEmoji);
430436
embed.WithColor(DiscordColor.Green);
431437

@@ -461,15 +467,22 @@ public async Task LogGiveawayExpirationAsync(Giveaway giveaway)
461467
description = $"{description[..1021]}...";
462468

463469
var entrantsCount = giveaway.Entrants.Count.ToString("N0");
464-
var excludedEntrantsCount = giveaway.Entrants.CountWhereNot(e => ValidateUser(e, guild, out _)).ToString("N0");
470+
var excludedEntrantsCount = 0;
471+
foreach (ulong entrantId in giveaway.Entrants)
472+
{
473+
DiscordMember? member = await ValidateUserAsync(entrantId, giveaway).ConfigureAwait(false);
474+
if (member is null) excludedEntrantsCount++;
475+
}
476+
477+
var excludedEntrants = excludedEntrantsCount.ToString("N0");
465478

466479
embed.AddField(EmbedStrings.Title, giveaway.Title);
467480
embed.AddField(EmbedStrings.Description, description);
468481
embed.AddField(EmbedStrings.Id, giveaway.Id, true);
469482
embed.AddField(EmbedStrings.NumberOfWinners, giveaway.WinnerCount, true);
470483
embed.AddField(EmbedStrings.Duration, (giveaway.EndTime - giveaway.StartTime).Humanize(), true);
471484
embed.AddField(EmbedStrings.Entrants, entrantsCount, true);
472-
embed.AddField(EmbedStrings.ExcludedEntrants, excludedEntrantsCount, true);
485+
embed.AddField(EmbedStrings.ExcludedEntrants, excludedEntrants, true);
473486

474487
var winners = new List<DiscordMember>();
475488
foreach (ulong winnerId in giveaway.WinnerIds)
@@ -518,7 +531,8 @@ public async Task LogGiveawayExpirationAsync(Giveaway giveaway)
518531
/// The selected winners of the giveaway. The returned list does not include invalid users, users which are no longer in
519532
/// the guild, or users with at least one of the excluded role IDs.
520533
/// </returns>
521-
public IReadOnlyList<DiscordMember> SelectWinners(Giveaway giveaway, IEnumerable<DiscordMember>? winnersToKeep = null)
534+
public async Task<IReadOnlyList<DiscordMember>> SelectWinnersAsync(Giveaway giveaway,
535+
IEnumerable<DiscordMember>? winnersToKeep = null)
522536
{
523537
ArgumentNullException.ThrowIfNull(giveaway);
524538

@@ -536,7 +550,8 @@ public IReadOnlyList<DiscordMember> SelectWinners(Giveaway giveaway, IEnumerable
536550
// in the event that there are zero valid winners
537551
entrants.Remove(randomUserId);
538552

539-
if (ValidateUser(randomUserId, guild, out DiscordMember? member))
553+
DiscordMember? member = await ValidateUserAsync(randomUserId, giveaway).ConfigureAwait(false);
554+
if (member is not null)
540555
winners.Add(member);
541556
}
542557

@@ -595,7 +610,7 @@ public async Task UpdateGiveawayLogMessageAsync(Giveaway giveaway)
595610
return;
596611
}
597612

598-
DiscordEmbed embed = CreateGiveawayLogEmbed(giveaway);
613+
DiscordEmbed embed = await CreateGiveawayLogEmbedAsync(giveaway).ConfigureAwait(false);
599614
await message.ModifyAsync(embed).ConfigureAwait(false);
600615
}
601616

@@ -667,21 +682,25 @@ public bool ValidateMember(DiscordMember member, DiscordGuild guild)
667682
/// Validates that the user with the specified ID is a valid participant of giveaways in the specified guild.
668683
/// </summary>
669684
/// <param name="userId">The ID of the user to validate.</param>
670-
/// <param name="guild">The guild in which to perform the validation check.</param>
671-
/// <param name="member">
672-
/// When this method returns, contains the <see cref="DiscordMember" /> with the ID <paramref name="userId" /> that is a
673-
/// member of <paramref name="guild" />.
674-
/// </param>
685+
/// <param name="giveaway">The giveaway used for validation.</param>
675686
/// <returns>
676-
/// <see langword="true" /> if the user with the ID <paramref name="userId" /> is a valid a participant of giveaways in
677-
/// <paramref name="guild" />; otherwise, <see langword="false" />.
687+
/// A <see cref="DiscordMember" /> object encapsulating the member as part of the guild in <paramref name="giveaway" />,
688+
/// if this user satisfies the giveaway requirements; otherwise, <see langword="null" />.
678689
/// </returns>
679-
/// <exception cref="ArgumentNullException"><paramref name="guild" /> is <see langword="null" />.</exception>
680-
public bool ValidateUser(ulong userId, DiscordGuild guild, [NotNullWhen(true)] out DiscordMember? member)
690+
/// <exception cref="ArgumentNullException"><paramref name="giveaway" /> is <see langword="null" />.</exception>
691+
public async Task<DiscordMember?> ValidateUserAsync(ulong userId, Giveaway giveaway)
681692
{
682-
ArgumentNullException.ThrowIfNull(guild);
683-
member = null;
684-
return userId != 0 && guild.Members.TryGetValue(userId, out member) && ValidateMember(member, guild);
693+
ArgumentNullException.ThrowIfNull(giveaway);
694+
695+
DiscordGuild guild = await _discordClient.GetGuildAsync(giveaway.GuildId).ConfigureAwait(false);
696+
DiscordMember? member = await guild.GetMemberOrNullAsync(userId).ConfigureAwait(false);
697+
698+
if (member is null) return null;
699+
if (!ValidateMember(member, guild)) return null;
700+
if (giveaway.ExcludedUsers.Contains(userId)) return null;
701+
if (member.Roles.Any(r => giveaway.ExcludedRoles.Contains(r.Id))) return null;
702+
703+
return member;
685704
}
686705

687706
private async Task UpdateFromDatabaseAsync(CancellationToken cancellationToken)

0 commit comments

Comments
 (0)