From f6d5281af81591cd04ff9f4a983876c991975ae9 Mon Sep 17 00:00:00 2001 From: Toutsu Date: Mon, 25 May 2026 17:53:40 +0300 Subject: [PATCH] fix(discord): resolve slash commands from interaction payload instead of gateway cache Context.Guild in NetCord resolves the Guild object from the gateway client cache (cache.Guilds.GetValueOrDefault(guildId)), not from the interaction JSON payload. After a bot restart, the guild may not yet be cached when the first slash command arrives, causing Context.Guild to be null even though the command is invoked inside a guild channel. This produced "This command can only be used in a guild." Changes: - DiscordListSessionsCommand: use Context.Interaction.GuildId instead of Context.Guild.Id - DiscordNewSessionCommand: use Context.Interaction.GuildId + REST GetGuildAsync/GetGuildUserAsync - DiscordRescheduleCommand: same as above - DiscordSessionInteractionModule: same fix for button interactions (CreateInput) - Add null guard in GetResolvedPermissions for safety - Bump version to 3.0.5 Co-Authored-By: Claude Opus 4.7 --- .gitea/workflows/deploy.yml | 2 +- Directory.Build.props | 2 +- compose.yaml | 6 +++--- .../Sessions/DiscordListSessionsCommand.cs | 2 +- .../Features/Sessions/DiscordNewSessionCommand.cs | 13 +++++++------ .../Features/Sessions/DiscordRescheduleCommand.cs | 13 ++++++++----- .../Sessions/DiscordSessionInteractionModule.cs | 4 ++-- src/GmRelay.Web/Components/Layout/NavMenu.razor | 2 +- .../Discord/DiscordProjectStructureTests.cs | 14 +++++++------- 9 files changed, 31 insertions(+), 27 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 34f1f77..b82e209 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -6,7 +6,7 @@ on: - main env: - VERSION: 3.0.4 + VERSION: 3.0.5 jobs: # ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами) diff --git a/Directory.Build.props b/Directory.Build.props index 933ddd6..a468115 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 3.0.4 + 3.0.5 net10.0 preview enable diff --git a/compose.yaml b/compose.yaml index f49d434..aa6da7a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -49,7 +49,7 @@ services: crond -f bot: - image: git.codeanddice.ru/toutsu/gmrelay-bot:3.0.4 + image: git.codeanddice.ru/toutsu/gmrelay-bot:3.0.5 restart: always depends_on: db: @@ -67,7 +67,7 @@ services: retries: 3 discord: - image: git.codeanddice.ru/toutsu/gmrelay-discord-bot:3.0.4 + image: git.codeanddice.ru/toutsu/gmrelay-discord-bot:3.0.5 restart: always depends_on: db: @@ -84,7 +84,7 @@ services: retries: 3 web: - image: git.codeanddice.ru/toutsu/gmrelay-web:3.0.4 + image: git.codeanddice.ru/toutsu/gmrelay-web:3.0.5 restart: always depends_on: db: diff --git a/src/GmRelay.DiscordBot/Features/Sessions/DiscordListSessionsCommand.cs b/src/GmRelay.DiscordBot/Features/Sessions/DiscordListSessionsCommand.cs index 5ce9d6f..e04a1cb 100644 --- a/src/GmRelay.DiscordBot/Features/Sessions/DiscordListSessionsCommand.cs +++ b/src/GmRelay.DiscordBot/Features/Sessions/DiscordListSessionsCommand.cs @@ -15,7 +15,7 @@ public class DiscordListSessionsCommand : ApplicationCommandModule - + diff --git a/tests/GmRelay.Bot.Tests/Discord/DiscordProjectStructureTests.cs b/tests/GmRelay.Bot.Tests/Discord/DiscordProjectStructureTests.cs index 64f156e..9ad6047 100644 --- a/tests/GmRelay.Bot.Tests/Discord/DiscordProjectStructureTests.cs +++ b/tests/GmRelay.Bot.Tests/Discord/DiscordProjectStructureTests.cs @@ -61,7 +61,7 @@ public sealed class DiscordProjectStructureTests var prChecks = File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "pr-checks.yml")); var deploy = File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml")); - Assert.Contains("gmrelay-discord-bot:3.0.4", compose); + Assert.Contains("gmrelay-discord-bot:3.0.5", compose); Assert.Contains("Discord__Token=${DISCORD_BOT_TOKEN:?Set DISCORD_BOT_TOKEN in .env}", compose); Assert.Contains("src/GmRelay.DiscordBot/Dockerfile", deploy); Assert.Contains("DISCORD_BOT_TOKEN", deploy); @@ -75,13 +75,13 @@ public sealed class DiscordProjectStructureTests { var repoRoot = GetRepoRoot(); - Assert.Contains("3.0.4", File.ReadAllText(Path.Combine(repoRoot, "Directory.Build.props"))); - Assert.Contains("VERSION: 3.0.4", File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml"))); - Assert.Contains("gmrelay-bot:3.0.4", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); - Assert.Contains("gmrelay-web:3.0.4", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); - Assert.Contains("gmrelay-discord-bot:3.0.4", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); + Assert.Contains("3.0.5", File.ReadAllText(Path.Combine(repoRoot, "Directory.Build.props"))); + Assert.Contains("VERSION: 3.0.5", File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml"))); + Assert.Contains("gmrelay-bot:3.0.5", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); + Assert.Contains("gmrelay-web:3.0.5", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); + Assert.Contains("gmrelay-discord-bot:3.0.5", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); Assert.Contains( - "v3.0.4", + "v3.0.5", File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.Web", "Components", "Layout", "NavMenu.razor"))); }