bwmarrin / discordgo

(Golang) Go bindings for Discord
BSD 3-Clause "New" or "Revised" License
5.11k stars 812 forks source link

Cannot reuse uploaded file as attachment #1551

Open toby3d opened 3 months ago

toby3d commented 3 months ago

I'm trying to implement a simple cache for regularly used files in slash command responses:

const SlashCommandName string = "poster"

// ...

func (i *Interaction) ServeInteraction(session *discordgo.Session, event *discordgo.InteractionCreate) {
    if event.Type != discordgo.InteractionApplicationCommand {
        return
    }

    data := event.ApplicationCommandData()
    if data.CommandType != discordgo.ChatApplicationCommand || !strings.EqualFold(data.Name, SlashCommandName) {
        return
    }

    go session.InteractionRespond(event.Interaction, &discordgo.InteractionResponse{
        Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
    })

    poster, err := i.chooser.Reveal(context.Background(), language.Make(string(event.Locale)))
    if err != nil {
        log.Fatalln(err)
    }
    defer poster.Release()

    // NOTE(toby3d): check what this poster is uploaded early, reuse it.
    if cachedMessageAttachment, cached := i.cache.Load("poster:" + poster.Name()); cached {
        if _, err = session.InteractionResponseEdit(event.Interaction, &discordgo.WebhookEdit{
            Attachments: &[]*discordgo.MessageAttachment{
                cachedMessageAttachment.(*discordgo.MessageAttachment),
            },
        }); err != nil {
            log.Fatalln("cannot send cached poster by URL:", err)
        }

        return
    }

    // NOTE(toby3d): it's a first time: upload poster as file, then store attachment in cache
    message, err := session.InteractionResponseEdit(event.Interaction, &discordgo.WebhookEdit{
        Files: []*discordgo.File{{
            Name:        poster.Name(),
            ContentType: poster.ContentType(),
            Reader:      poster.Image(),
        }},
        Attachments: &[]*discordgo.MessageAttachment{{
            ID:  "0",
            URL: "attachment://" + poster.Name(),
        }},
    })
    if err != nil {
        log.Fatalln(err)
    }

    i.cache.Store("poster:"+poster.Name(), message.Attachments[0])
}

But sending data from the cache regularly results in an error:

cannot send cached poster by URL: HTTP 400 Bad Request, {"message": "Invalid Form Body", "code": 50035, "errors": {"attachments": {"0": {"_errors": [{"code": "ATTACHMENT_NOT_FOUND", "message": "Attachment data not found"}]}}}}
exit status 1

If I use just attachment URL, then I got error about "Invalid attachment ID".

If I use the URL of the uploaded file as an image, however, it embeds with a border that I want to avoid: image

However, if I use the URL of the uploaded file as is, using it in Content, it uploads at a smaller size than the original in the client interface: image