using GmRelay.DiscordBot.Rendering; using NetCord.Rest; using NetCord.Services.ApplicationCommands; namespace GmRelay.DiscordBot.Features.Sessions; [SlashCommand("newsession", "Create a new game session")] public class DiscordNewSessionCommand : ApplicationCommandModule { private readonly DiscordNewSessionHandler _handler; private readonly ILogger _logger; public DiscordNewSessionCommand(DiscordNewSessionHandler handler, ILogger logger) { _handler = handler; _logger = logger; } public async Task ExecuteAsync( [SlashCommandParameter(Name = "title", Description = "Game title")] string title, [SlashCommandParameter(Name = "time", Description = "Session time (YYYY-MM-DD HH:mm or DD.MM.YYYY HH:mm)")] string time, [SlashCommandParameter(Name = "seats", Description = "Maximum number of players")] long? seats = null, [SlashCommandParameter(Name = "link", Description = "Join link")] string? link = null) { var guild = Context.Guild ?? throw new InvalidOperationException("This command can only be used in a guild."); var timeResult = DiscordNewSessionHandler.ParseTimeInput(time); if (!timeResult.IsSuccess) { await Context.Interaction.SendResponseAsync( InteractionCallback.Message($"X {timeResult.Error}")); return; } var resolvedPermissions = GetResolvedPermissions(guild, Context.User.Id); try { var view = await _handler.HandleAsync( guildId: guild.Id.ToString(), channelId: Context.Channel.Id.ToString(), userId: Context.User.Id, userDisplayName: Context.User.GlobalName ?? Context.User.Username, resolvedPermissions: resolvedPermissions, guildOwnerId: guild.OwnerId, title: title, scheduledAt: timeResult.Value, maxPlayers: seats is null ? null : (int)seats.Value, joinLink: link, CancellationToken.None); var (embeds, actionRows) = DiscordSessionBatchRenderer.Render(view); await Context.Interaction.SendResponseAsync( InteractionCallback.Message(new InteractionMessageProperties() .WithContent(":white_check_mark: **Session created successfully!**") .WithEmbeds(embeds) .WithComponents(actionRows))); } catch (UnauthorizedAccessException ex) { await Context.Interaction.SendResponseAsync( InteractionCallback.Message($":no_entry: {ex.Message}")); } catch (Exception ex) { _logger.LogError(ex, "Failed to create session for user {UserId} in guild {GuildId}", Context.User.Id, guild.Id); await Context.Interaction.SendResponseAsync( InteractionCallback.Message(":boom: An error occurred while creating the session.")); } } private static ulong GetResolvedPermissions(NetCord.Gateway.Guild guild, ulong userId) { if (!guild.Users.TryGetValue(userId, out var guildUser)) return 0; ulong resolved = 0; foreach (var roleId in guildUser.RoleIds) { if (guild.Roles.TryGetValue(roleId, out var role)) resolved |= (ulong)role.Permissions; } return resolved; } }