diff --git a/Cocotte/Modules/Activities/ActivityModule.cs b/Cocotte/Modules/Activities/ActivityModule.cs index bf43ca1..3d95c0d 100644 --- a/Cocotte/Modules/Activities/ActivityModule.cs +++ b/Cocotte/Modules/Activities/ActivityModule.cs @@ -138,8 +138,7 @@ public partial class ActivityModule : InteractionModuleBase ***Création de l'activité en cours...***"); @@ -147,7 +146,7 @@ public partial class ActivityModule : InteractionModuleBase= activity.MaxPlayers) - { - await RespondAsync( - ephemeral: true, - embed: EmbedUtils.ErrorEmbed("L'activité est **complète**").Build() - ); - - return; - } - - _logger.LogTrace("Player {Player} joined activity {Id}", user.DisplayName, messageId); - - var activityPlayer = CreateActivityPlayer(activity, User, activity.AreRolesEnabled); - - // Add player to activity - activity.ActivityPlayers.Add(activityPlayer); - await _activitiesRepository.SaveChanges(); - - // Update activity embed - await UpdateActivityEmbed(activity, ActivityUpdateReason.PlayerJoin); - await RespondAsync( ephemeral: true, embed: EmbedUtils.SuccessEmbed("Vous avez bien été **inscrit** pour cette activité").Build() @@ -302,8 +271,6 @@ public partial class ActivityModule : InteractionModuleBase AddUserToActivity(Activity activity, SocketGuildUser user, bool self) + { + // If player is already registered + if (await _activitiesRepository.FindActivityPlayer(activity.GuildId, activity.ChannelId, activity.MessageId, user.Id) is not + null) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed(self ? "Vous êtes **déjà inscrit** à cette activité" : $"{user.DisplayName} est **déjà inscrit** à cette activité").Build() + ); + + return false; + } + + // Check if activity is full + if (await _activitiesRepository.ActivityPlayerCount(activity) >= activity.MaxPlayers) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed("L'activité est **complète**").Build() + ); + + return false; + } + + _logger.LogTrace("Player {Player} joined activity {Id}", user.DisplayName, activity.MessageId); + + var activityPlayer = CreateActivityPlayer(activity, user, activity.AreRolesEnabled); + + // Add player to activity + activity.ActivityPlayers.Add(activityPlayer); + await _activitiesRepository.SaveChanges(); + + // Update activity embed + await UpdateActivityEmbed(activity, ActivityUpdateReason.PlayerJoin); + + // Send join message to thread and add user to thread + var thread = Context.Guild.GetThreadChannel(activity.ThreadId); + + await thread.AddUserAsync(user); + + string embedContent = $"**{user.DisplayName}** a été **ajouté** à l'activité"; + if (self) + { + await thread.SendMessageAsync( + embed: EmbedUtils.InfoEmbed(embedContent).Build() + ); + } + else + { + await RespondAsync( + embed: EmbedUtils.InfoEmbed(embedContent).Build() + ); + } + + return true; + } + + private async Task RemovePlayerFromActivity(Activity activity, SocketGuildUser user, bool self) + { + // Check if player is in activity + if (await _activitiesRepository.FindActivityPlayer(activity.GuildId, activity.ChannelId, activity.MessageId, user.Id) is not { } activityPlayer) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed(self ? "Vous n'êtes **pas inscrit** à cette activité" : $"{user.DisplayName} n'est **pas inscrit** à cette activité").Build() + ); + + return false; + } + + _logger.LogTrace("Player {Player} left activity {Id}", user.DisplayName, activity.MessageId); + + activity.ActivityPlayers.Remove(activityPlayer); + await _activitiesRepository.SaveChanges(); + + // Update activity embed + await UpdateActivityEmbed(activity, ActivityUpdateReason.PlayerLeave); + + // Send leave message to thread and remove user from thread + var thread = Context.Guild.GetThreadChannel(activity.ThreadId); + + await thread.RemoveUserAsync(user); + + string embedContent = $"{user.DisplayName} a été **enlevé** de l'activité"; + if (self) + { + await thread.SendMessageAsync( + embed: EmbedUtils.InfoEmbed(embedContent).Build() + ); + } + else + { + await RespondAsync( + embed: EmbedUtils.InfoEmbed(embedContent).Build() + ); + } + + return true; + } + private async Task UpdateActivityEmbed(Activity activity, ActivityUpdateReason updateReason) { // Get channel diff --git a/Cocotte/Modules/Activities/ActivityModuleThread.cs b/Cocotte/Modules/Activities/ActivityModuleThread.cs index f4755f6..62fb66b 100644 --- a/Cocotte/Modules/Activities/ActivityModuleThread.cs +++ b/Cocotte/Modules/Activities/ActivityModuleThread.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Text; using Cocotte.Modules.Activities.Models; using Cocotte.Utils; using Discord; @@ -56,34 +57,12 @@ public partial class ActivityModule return; } - // Check that the user is not already in the activity - if (await _activitiesRepository.ActivityContainsUser(activity, user.Id)) - { - await RespondAsync( - ephemeral: true, - embed: EmbedUtils.ErrorEmbed("Cet utilisateur est **déjà inscrit** à cette activité").Build() - ); - - return; - } - - var activityPlayer = CreateActivityPlayer(activity, (SocketGuildUser) user, activity.AreRolesEnabled); - - activity.ActivityPlayers.Add(activityPlayer); - await _activitiesRepository.SaveChanges(); - - await UpdateActivityEmbed(activity, ActivityUpdateReason.PlayerJoin); - - await RespondAsync( - ephemeral: true, - embed: EmbedUtils.SuccessEmbed($"{((IGuildUser) user).DisplayName} a bien été **ajouté** à l'activité").Build() - ); + await AddUserToActivity(activity, (SocketGuildUser) user, self: false); } - [SlashCommand("ajouter", "Ajouter un joueur à cette activité")] + [SlashCommand("enlever", "Enlever un joueur de cette activité")] public async Task ThreadRemovePlayer(IUser user) { - // TODO: Autocomplete // Get activity linked to this thread var activity = _activitiesRepository.FindActivityByThreadId(Context.Channel.Id); @@ -92,31 +71,32 @@ public partial class ActivityModule return; } - // Check that the user is not already in the activity - if (await _activitiesRepository.ActivityContainsUser(activity, user.Id)) - { - await RespondAsync( - ephemeral: true, - embed: EmbedUtils.ErrorEmbed("Cet utilisateur est **déjà inscrit** à cette activité").Build() - ); + await RemovePlayerFromActivity(activity, (SocketGuildUser) user, self: false); + } + [SlashCommand("ping", "Ping les joueurs inscrits à cette activité")] + public async Task ThreadPingPlayers(string message = "**Appel de groupe**") + { + // Get activity linked to this thread + var activity = _activitiesRepository.FindActivityByThreadId(Context.Channel.Id); + + if (!await CheckCommandInThread(activity) || activity is null) + { return; } - var activityPlayer = CreateActivityPlayer(activity, (SocketGuildUser) user, activity.AreRolesEnabled); + // Get user ids + var userIds = await _activitiesRepository.GetActivityPlayerIds(activity); - activity.ActivityPlayers.Add(activityPlayer); - await _activitiesRepository.SaveChanges(); - await UpdateActivityEmbed(activity, ActivityUpdateReason.PlayerJoin); + // Generate message + var pingMessageBuilder = new StringBuilder(message); + pingMessageBuilder.AppendLine("\n"); + pingMessageBuilder.Append(string.Join(", ", userIds.Select(id => MentionUtils.MentionUser(id)))); - await RespondAsync( - ephemeral: true, - embed: EmbedUtils.SuccessEmbed($"{((IGuildUser) user).DisplayName} a bien été **ajouté** à l'activité").Build() - ); + await RespondAsync(pingMessageBuilder.ToString()); } - private async Task CheckCommandInThread(Activity? activity) { // Check if activity is not null (means we are in a valid thread) diff --git a/Cocotte/Modules/Activities/Models/ActivitiesRepository.cs b/Cocotte/Modules/Activities/Models/ActivitiesRepository.cs index 2e290c1..ff4ec93 100644 --- a/Cocotte/Modules/Activities/Models/ActivitiesRepository.cs +++ b/Cocotte/Modules/Activities/Models/ActivitiesRepository.cs @@ -22,7 +22,7 @@ public class ActivitiesRepository return await _cocotteDbContext.ActivityPlayers.FindAsync(guildId, channelId, messageId, userId); } - public int ActivityPlayerCount(Activity activity) => activity.ActivityPlayers.Count; + public async Task ActivityPlayerCount(Activity activity) => await _cocotteDbContext.Entry(activity).Collection(a => a.ActivityPlayers).Query().CountAsync(); public async Task> LoadActivityPlayers(Activity activity) { @@ -61,4 +61,13 @@ public class ActivitiesRepository .Query() .AnyAsync(p => p.UserId == userId); } + + public async Task> GetActivityPlayerIds(Activity activity) + { + return await _cocotteDbContext.Entry(activity) + .Collection(a => a.ActivityPlayers) + .Query() + .Select(p => p.UserId) + .ToListAsync(); + } } \ No newline at end of file diff --git a/Cocotte/Program.cs b/Cocotte/Program.cs index 00604b7..e22f8ad 100644 --- a/Cocotte/Program.cs +++ b/Cocotte/Program.cs @@ -72,7 +72,7 @@ await using(var scope = host.Services.CreateAsyncScope()) if (hostEnvironment.IsDevelopment()) { var dbContext = scope.ServiceProvider.GetRequiredService(); - await dbContext.Database.EnsureDeletedAsync(); + // await dbContext.Database.EnsureDeletedAsync(); await dbContext.Database.EnsureCreatedAsync(); } }