[Activity] Add thread ping and refactor activity join/leave

This commit is contained in:
2023-03-24 23:39:35 +01:00
parent a3051ed060
commit ced9d15083
4 changed files with 139 additions and 98 deletions

View File

@@ -138,8 +138,7 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
private async Task CreateActivity(ActivityName activityName, string description, bool areRolesEnabled = true, uint? maxPlayers = null, uint? stage = null, InterstellarColor? interstellarColor = null)
{
var user = (SocketGuildUser)Context.User;
_logger.LogTrace("{User} is creating activity {Activity}", user.DisplayName, activityName);
_logger.LogTrace("{User} is creating activity {Activity}", User.DisplayName, activityName);
// Activities are identified using their original message id
await RespondAsync("> ***Création de l'activité en cours...***");
@@ -147,7 +146,7 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
var response = await GetOriginalResponseAsync();
// Create associated thread
var threadId = await CreateThread(activityName, user.DisplayName);
var threadId = await CreateThread(activityName, User.DisplayName);
var activityType = ActivityHelper.ActivityNameToType(activityName);
maxPlayers ??= ActivityHelper.ActivityTypeToMaxPlayers(activityType);
@@ -202,7 +201,7 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
Description = description,
Type = activityType,
Name = activityName,
AreRolesEnabled = true,
AreRolesEnabled = areRolesEnabled,
MaxPlayers = (uint) maxPlayers
};
}
@@ -211,7 +210,7 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
await _activitiesRepository.AddActivity(activity);
// Add creator to activity
var rolePlayer = CreateActivityPlayer(activity, user, areRolesEnabled);
var rolePlayer = CreateActivityPlayer(activity, User, areRolesEnabled);
activity.ActivityPlayers.Add(rolePlayer);
@@ -247,8 +246,6 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
[ComponentInteraction("activity join:*", ignoreGroupNames: true)]
public async Task JoinActivity(ulong messageId)
{
var user = (SocketGuildUser)Context.User;
// Check if activity exists
if (await _activitiesRepository.FindActivity(Context.Guild.Id, Context.Channel.Id, messageId) is not { } activity)
{
@@ -260,39 +257,11 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
return;
}
// If player is already registered
if (await _activitiesRepository.FindActivityPlayer( Context.Guild.Id, Context.Channel.Id, messageId, user.Id) is not null)
if (!await AddUserToActivity(activity, User, self: true))
{
await RespondAsync(
ephemeral: true,
embed: EmbedUtils.ErrorEmbed("Vous êtes **déjà inscrit** à cette activité").Build()
);
return;
}
// Check if activity is full
if (_activitiesRepository.ActivityPlayerCount(activity) >= 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<SocketInteractionCon
[ComponentInteraction("activity leave:*", ignoreGroupNames: true)]
public async Task LeaveActivity(ulong messageId)
{
var user = (IGuildUser)Context.User;
// Check if activity exists
if (await _activitiesRepository.FindActivity(Context.Guild.Id, Context.Channel.Id, messageId) is not { } activity)
{
@@ -315,25 +282,11 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
return;
}
// Check if player is in activity
if (await _activitiesRepository.FindActivityPlayer(Context.Guild.Id, Context.Channel.Id, messageId, user.Id) is not { } activityPlayer)
if (!await RemovePlayerFromActivity(activity, User, self: true))
{
await RespondAsync(
ephemeral: true,
embed: EmbedUtils.ErrorEmbed("Vous n'êtes **pas inscrit** à cette activité").Build()
);
return;
}
_logger.LogTrace("Player {Player} left activity {Id}", user.DisplayName, messageId);
activity.ActivityPlayers.Remove(activityPlayer);
await _activitiesRepository.SaveChanges();
// Update activity embed
await UpdateActivityEmbed(activity, ActivityUpdateReason.PlayerLeave);
await RespondAsync(
ephemeral: true,
embed: EmbedUtils.SuccessEmbed("Vous avez bien été **désinscrit** pour cette activité").Build()
@@ -343,8 +296,6 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
[ComponentInteraction("activity delete:*", ignoreGroupNames: true)]
public async Task DeleteActivity(ulong messageId)
{
var user = (SocketGuildUser) Context.User;
// Check if activity exists
if (await _activitiesRepository.FindActivity(Context.Guild.Id, Context.Channel.Id, messageId) is not { } activity)
{
@@ -357,7 +308,7 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
}
// Check if user has permission to delete this activity
if (user.Id != activity.CreatorUserId && !user.GetPermissions((IGuildChannel) Context.Channel).ManageMessages)
if (User.Id != activity.CreatorUserId && !User.GetPermissions((IGuildChannel) Context.Channel).ManageMessages)
{
await RespondAsync(
ephemeral: true,
@@ -378,6 +329,107 @@ public partial class ActivityModule : InteractionModuleBase<SocketInteractionCon
await Context.Channel.DeleteMessageAsync(messageId);
}
private async Task<bool> 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<bool> 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

View File

@@ -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<bool> CheckCommandInThread(Activity? activity)
{
// Check if activity is not null (means we are in a valid thread)

View File

@@ -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<int> ActivityPlayerCount(Activity activity) => await _cocotteDbContext.Entry(activity).Collection(a => a.ActivityPlayers).Query().CountAsync();
public async Task<IReadOnlyCollection<ActivityPlayer>> LoadActivityPlayers(Activity activity)
{
@@ -61,4 +61,13 @@ public class ActivitiesRepository
.Query()
.AnyAsync(p => p.UserId == userId);
}
public async Task<IList<ulong>> GetActivityPlayerIds(Activity activity)
{
return await _cocotteDbContext.Entry(activity)
.Collection(a => a.ActivityPlayers)
.Query()
.Select(p => p.UserId)
.ToListAsync();
}
}

View File

@@ -72,7 +72,7 @@ await using(var scope = host.Services.CreateAsyncScope())
if (hostEnvironment.IsDevelopment())
{
var dbContext = scope.ServiceProvider.GetRequiredService<CocotteDbContext>();
await dbContext.Database.EnsureDeletedAsync();
// await dbContext.Database.EnsureDeletedAsync();
await dbContext.Database.EnsureCreatedAsync();
}
}