129 lines
5.2 KiB
C#
129 lines
5.2 KiB
C#
using GmRelay.DiscordBot.Rendering;
|
|
using NetCord;
|
|
using NetCord.Rest;
|
|
using NetCord.Services.ApplicationCommands;
|
|
|
|
namespace GmRelay.DiscordBot.Features.Sessions;
|
|
|
|
public class DiscordNewSessionCommand : ApplicationCommandModule<SlashCommandContext>
|
|
{
|
|
private readonly DiscordNewSessionHandler _handler;
|
|
private readonly ILogger<DiscordNewSessionCommand> _logger;
|
|
|
|
public DiscordNewSessionCommand(DiscordNewSessionHandler handler, ILogger<DiscordNewSessionCommand> logger)
|
|
{
|
|
_handler = handler;
|
|
_logger = logger;
|
|
}
|
|
|
|
[SlashCommand("newsession", "Create a new game session")]
|
|
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)
|
|
{
|
|
_logger.LogInformation(
|
|
"newsession called by user {UserId} ({UserType}) in guild {GuildId}, channel {ChannelId}",
|
|
Context.User.Id,
|
|
Context.User.GetType().Name,
|
|
Context.Interaction.GuildId,
|
|
Context.Channel?.Id);
|
|
|
|
var guildId = Context.Interaction.GuildId
|
|
?? throw new InvalidOperationException("This command can only be used in a guild.");
|
|
|
|
var member = Context.User as GuildInteractionUser;
|
|
if (member is null)
|
|
{
|
|
_logger.LogError("Context.User is not GuildInteractionUser. Actual type: {ActualType}", Context.User.GetType().Name);
|
|
throw new InvalidOperationException("Guild member data not available in interaction.");
|
|
}
|
|
|
|
var resolvedPermissions = (ulong)member.Permissions;
|
|
_logger.LogInformation("Resolved permissions for user {UserId}: {Permissions}", Context.User.Id, resolvedPermissions);
|
|
|
|
ulong guildOwnerId = 0;
|
|
var guildName = guildId.ToString();
|
|
try
|
|
{
|
|
var guild = await Context.Client.Rest.GetGuildAsync(guildId);
|
|
guildOwnerId = guild.OwnerId;
|
|
guildName = guild.Name;
|
|
_logger.LogInformation("Guild owner id: {OwnerId}", guildOwnerId);
|
|
}
|
|
catch (RestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
|
|
{
|
|
_logger.LogWarning(
|
|
ex,
|
|
"Bot is not a REST member of guild {GuildId}; using resolved permissions from interaction payload",
|
|
guildId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Unexpected error fetching guild {GuildId}", guildId);
|
|
}
|
|
|
|
var timeResult = DiscordNewSessionHandler.ParseTimeInput(time);
|
|
if (!timeResult.IsSuccess)
|
|
{
|
|
await Context.Interaction.SendResponseAsync(
|
|
InteractionCallback.Message($"X {timeResult.Error}"));
|
|
return;
|
|
}
|
|
|
|
// Defer the response to avoid Discord 3-second interaction timeout
|
|
await Context.Interaction.SendResponseAsync(InteractionCallback.DeferredMessage());
|
|
|
|
try
|
|
{
|
|
_logger.LogInformation("Creating session for guild {GuildId}, user {UserId}", guildId, Context.User.Id);
|
|
|
|
var view = await _handler.HandleAsync(
|
|
guildId: guildId.ToString(),
|
|
channelId: Context.Channel!.Id.ToString(),
|
|
groupName: guildName,
|
|
userId: Context.User.Id,
|
|
userDisplayName: Context.User.GlobalName ?? Context.User.Username,
|
|
resolvedPermissions: resolvedPermissions,
|
|
guildOwnerId: guildOwnerId,
|
|
title: title,
|
|
scheduledAt: timeResult.Value,
|
|
maxPlayers: seats is null ? null : (int)seats.Value,
|
|
joinLink: link,
|
|
CancellationToken.None);
|
|
|
|
_logger.LogInformation("Session created successfully. Building render.");
|
|
|
|
var (embeds, actionRows) = DiscordSessionBatchRenderer.Render(view);
|
|
|
|
_logger.LogInformation("Sending success response.");
|
|
|
|
await Context.Interaction.ModifyResponseAsync(message =>
|
|
{
|
|
message.Content = ":white_check_mark: **Session created successfully!**";
|
|
message.Embeds = embeds;
|
|
message.Components = actionRows;
|
|
});
|
|
|
|
_logger.LogInformation("Success response sent.");
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
_logger.LogWarning(ex, "Unauthorized session creation attempt by user {UserId}", Context.User.Id);
|
|
await Context.Interaction.ModifyResponseAsync(message =>
|
|
{
|
|
message.Content = $":no_entry: {ex.Message}";
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Failed to create session for user {UserId} in guild {GuildId}", Context.User.Id, guildId);
|
|
await Context.Interaction.ModifyResponseAsync(message =>
|
|
{
|
|
message.Content = ":boom: An error occurred while creating the session.";
|
|
});
|
|
}
|
|
}
|
|
}
|