From 5bc2da4ad80cccab14c8944ecf44351a341620b6 Mon Sep 17 00:00:00 2001 From: FernandoJVideira <03.pleaser-minster@icloud.com> Date: Fri, 23 Oct 2026 11:57:30 +0100 Subject: [PATCH] Help: log whether the bot is a member of the server when the DM fails Co-Authored-By: Claude Sonnet 5.5 --- internal/commands/help/help.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/internal/commands/help/help.go b/internal/commands/help/help.go index 8a34e28..b8bad42 100644 --- a/internal/commands/help/help.go +++ b/internal/commands/help/help.go @@ -1,6 +1,7 @@ package help import ( + "fmt" "log" "unicode/utf8" @@ -139,8 +140,8 @@ func HelpHandler(s *discordgo.Session, i *discordgo.InteractionCreate) { // when "no mutual guilds" appears for someone who is in a server with // the bot: a command run through a user install, or in a server the bot // isn't actually a member of, has no shared server for Discord to see. - log.Printf("help: DM not possible, showing it here (guild %q, context %d, installs %v): %v", - i.GuildID, i.Context, i.AuthorizingIntegrationOwners, err) + log.Printf("help: DM not possible, showing it here (guild %q, context %d, installs %v, %s): %v", + i.GuildID, i.Context, i.AuthorizingIntegrationOwners, botMembership(s, i.GuildID), err) note := "I couldn't DM you (your DMs may be off), so here it is." _, _ = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{Content: ¬e, Embeds: &list}) return @@ -161,3 +162,21 @@ func sendByDM(s *discordgo.Session, userID string, list []*discordgo.MessageEmbe } return nil } + +// botMembership says whether the bot is really a member of the server, which +// is what Discord means by "mutual guilds". A server where the app was added +// with only the applications.commands scope runs slash commands fine but has +// no bot user in it. +func botMembership(s *discordgo.Session, guildID string) string { + if s == nil || s.State == nil || s.State.User == nil { + return "bot user unknown" + } + inCache := false + if g, err := s.State.Guild(guildID); err == nil && g != nil { + inCache = true + } + if _, err := s.GuildMember(guildID, s.State.User.ID); err != nil { + return fmt.Sprintf("bot is NOT a member of that server (in gateway cache: %v): %v", inCache, err) + } + return fmt.Sprintf("bot is a member of that server (in gateway cache: %v)", inCache) +}