1111using Microsoft . Extensions . Hosting ;
1212using NLog ;
1313using SmartFormat ;
14- using X10D . Collections ;
1514using X10D . Core ;
1615using 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