From 6cff82b0df3975d047625c0ed7c0046eefd69b1b Mon Sep 17 00:00:00 2001 From: Vovko Date: Tue, 31 Mar 2026 21:33:19 -0500 Subject: [PATCH] handle missing permission errors --- cmd/discord/gateway/context.go | 10 +++++++++- cmd/discord/router/context.go | 23 ++++++++++++++++++++++- static/localization/en/discord.yaml | 1 + static/localization/pl/discord.yaml | 1 + static/localization/pt-BR/discord.yaml | 1 + 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/cmd/discord/gateway/context.go b/cmd/discord/gateway/context.go index 83f8bb56..7b668490 100644 --- a/cmd/discord/gateway/context.go +++ b/cmd/discord/gateway/context.go @@ -127,7 +127,15 @@ func (c *eventContext) saveInteractionEvent(msg discordgo.Message, msgErr error, } } func (c *eventContext) InteractionResponse(reply common.Reply) (discordgo.Message, error) { - return c.CreateMessage(c.Context, c.channelID, reply) + msg, err := c.CreateMessage(c.Context, c.channelID, reply) + // missing permissions with files - send a permissions error instead + if errors.Is(err, rest.ErrMissingPermissions) && len(reply.Peek().Files) > 0 { + msg, err = c.gw.rest.CreateMessage(c.Context, c.channelID, discordgo.MessageSend{ + Content: c.localize("common_error_missing_permissions_images"), + Reference: reply.Peek().Reference, + }, nil) + } + return msg, err } func (c *eventContext) InteractionFollowUp(ctx context.Context, reply common.Reply) (discordgo.Message, error) { diff --git a/cmd/discord/router/context.go b/cmd/discord/router/context.go index 782dcef5..db5669c6 100644 --- a/cmd/discord/router/context.go +++ b/cmd/discord/router/context.go @@ -10,6 +10,7 @@ import ( "github.com/cufee/aftermath/cmd/discord/common" "github.com/cufee/aftermath/cmd/discord/rest" "github.com/cufee/aftermath/internal/database" + "github.com/cufee/aftermath/internal/retry" "github.com/cufee/aftermath/internal/database/models" "github.com/cufee/aftermath/internal/external/averages" "github.com/cufee/aftermath/internal/localization" @@ -122,7 +123,7 @@ func (c *routeContext) InteractionResponse(reply common.Reply) (discordgo.Messag go c.saveInteractionEvent(discordgo.Message{}, c.Context.Err(), reply) return discordgo.Message{}, c.Context.Err() default: - msg, err := common.WithRetry(func() (discordgo.Message, error) { + res := retry.Retry(func() (discordgo.Message, error) { // since we already finished handling the interaction, there is no need to use the handler context ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) defer cancel() @@ -135,7 +136,20 @@ func (c *routeContext) InteractionResponse(reply common.Reply) (discordgo.Messag return discordgo.Message{}, err } return c.rest.UpdateInteractionResponse(ctx, c.interaction.AppID, c.interaction.Token, data.Interaction(), files) + }, 5, time.Second, func(err error) bool { + // do not retry on missing permissions, they will not change between retries + return errors.Is(err, rest.ErrMissingPermissions) }) + msg, err := res.Data, res.Err + + // missing permissions with files - send a permissions error instead + if errors.Is(err, rest.ErrMissingPermissions) && len(files) > 0 { + permData := discordgo.InteractionResponseData{Content: c.localize("common_error_missing_permissions_images")} + retryCtx, cancel := context.WithTimeout(context.Background(), time.Second*2) + defer cancel() + msg, err = c.rest.UpdateInteractionResponse(retryCtx, c.interaction.AppID, c.interaction.Token, permData, nil) + } + if errors.Is(err, rest.ErrUnknownInteraction) || errors.Is(err, rest.ErrUnknownWebhook) { // Discord did not propagate the ack, this happens on low usage discord servers sometimes message := data.Message() @@ -144,6 +158,13 @@ func (c *routeContext) InteractionResponse(reply common.Reply) (discordgo.Messag fallbackCtx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() msg, err = c.rest.CreateMessage(fallbackCtx, c.interaction.ChannelID, message, files) + + // channel message also failed on permissions with files - send permissions error only + if errors.Is(err, rest.ErrMissingPermissions) && len(files) > 0 { + msg, err = c.rest.CreateMessage(fallbackCtx, c.interaction.ChannelID, discordgo.MessageSend{ + Content: c.localize("common_error_missing_permissions_images"), + }, nil) + } } go c.saveInteractionEvent(msg, err, reply) diff --git a/static/localization/en/discord.yaml b/static/localization/en/discord.yaml index 0e074e74..0d913e69 100644 --- a/static/localization/en/discord.yaml +++ b/static/localization/en/discord.yaml @@ -128,6 +128,7 @@ common_error_command_missing_permissions: "You don't have permission to use this common_error_discord_outage: "It looks like Discord is having some temporary issues. Please try again in a few seconds." common_error_missing_permissions_dm: "Aftermath is not able to send you a direct message." common_error_missing_permissions_dm_mention_fmt: "Hey %s, Aftermath is not able to send you a direct message." +common_error_missing_permissions_images: "Aftermath is missing permissions to send images in this channel. Please make sure the bot has the **Attach Files** permission enabled." common_error_payment_required: |- This feature of Aftermath is only available for users with an active subscription. You can subscribe by using the `/subscribe` command. diff --git a/static/localization/pl/discord.yaml b/static/localization/pl/discord.yaml index c20dfddb..0272385e 100644 --- a/static/localization/pl/discord.yaml +++ b/static/localization/pl/discord.yaml @@ -128,6 +128,7 @@ common_error_command_missing_permissions: "Nie masz uprawnień do użycia tego p common_error_discord_outage: "Wygląda na to, że Discord ma chwilowe problemy. Spróbuj ponownie za kilka sekund." common_error_missing_permissions_dm: "Aftermath nie jest w stanie wysłać Ci bezpośredniej wiadomości." common_error_missing_permissions_dm_mention_fmt: "Hej %s, Aftermath nie jest w stanie wysłać Ci bezpośredniej wiadomości." +common_error_missing_permissions_images: "Aftermath nie ma uprawnień do wysyłania obrazów na tym kanale. Upewnij się, że bot ma włączone uprawnienie **Attach Files**." common_error_payment_required: |- Ta funkcja Aftermath jest dostępna tylko dla użytkowników z aktywną subskrypcją. Możesz subskrybować, używając polecenia `/subscribe`. diff --git a/static/localization/pt-BR/discord.yaml b/static/localization/pt-BR/discord.yaml index 5666aacc..5e865244 100644 --- a/static/localization/pt-BR/discord.yaml +++ b/static/localization/pt-BR/discord.yaml @@ -128,6 +128,7 @@ common_error_command_missing_permissions: "Você não tem permissão para usar e common_error_discord_outage: "Parece que o Discord está com problemas temporários. Tente novamente em alguns segundos." common_error_missing_permissions_dm: "O Aftermath não pode te enviar uma mensagem direta." common_error_missing_permissions_dm_mention_fmt: "Olá %s, o Aftermath não pode lhe enviar uma mensagem direta." +common_error_missing_permissions_images: "O Aftermath não tem permissões para enviar imagens neste canal. Certifique-se de que o bot tenha a permissão **Attach Files** ativada." common_error_payment_required: |- Este recurso é exclusivo de assinantes. Você pode ter uma assinatura pelo comando `/subscribe`.