discord: support sending files with just a URL

previously, the code assumed each file had a Data, and crashed if this was not present.
now, we detect this condition, and send the URL instead.

the discord client will display URLs in a message of their own
as inline embeds, without any special behavior needed on our part.

this commit makes the same changes to the webhook and non-webhook code.
This commit is contained in:
ubq323 2024-08-16 10:04:12 +01:00
parent e168a89632
commit 707a74ba0e
2 changed files with 90 additions and 35 deletions

View File

@ -380,26 +380,51 @@ func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (st
// handleUploadFile handles native upload of files // handleUploadFile handles native upload of files
func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (string, error) { func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (string, error) {
for _, f := range msg.Extra["file"] { for _, f := range msg.Extra["file"] {
var err error
fi := f.(config.FileInfo) fi := f.(config.FileInfo)
file := discordgo.File{
Name: fi.Name, if fi.URL != "" {
ContentType: "", err = b.handleUploadFileFromURL(msg, channelID, &fi)
Reader: bytes.NewReader(*fi.Data), } else if fi.Data != nil {
} err = b.handleUploadFileFromData(msg, channelID, &fi)
m := discordgo.MessageSend{ } else {
Content: msg.Username + fi.Comment, b.Log.Errorf("Attachment %#v for message %#v had neither Data nor URL", fi, msg)
Files: []*discordgo.File{&file},
AllowedMentions: b.getAllowedMentions(),
}
res, err := b.c.ChannelMessageSendComplex(channelID, &m)
if err != nil {
return "", fmt.Errorf("file upload failed: %s", err)
} }
// link file_upload_nativeID (file ID from the original bridge) to our upload id if err != nil {
// so that we can remove this later when it eg needs to be deleted b.Log.Errorf("Could not send attachment %#v for message %#v: %s", fi, msg, err)
b.cache.Add(cFileUpload+fi.NativeID, res.ID) return "", err
}
} }
return "", nil return "", nil
} }
func (b *Bdiscord) handleUploadFileFromData(msg *config.Message, channelID string, fi *config.FileInfo) error {
file := discordgo.File{
Name: fi.Name,
ContentType: "",
Reader: bytes.NewReader(*fi.Data),
}
m := discordgo.MessageSend{
Content: msg.Username + fi.Comment,
Files: []*discordgo.File{&file},
AllowedMentions: b.getAllowedMentions(),
}
res, err := b.c.ChannelMessageSendComplex(channelID, &m)
if err != nil {
return fmt.Errorf("file upload failed: %s", err)
}
// link file_upload_nativeID (file ID from the original bridge) to our upload id
// so that we can remove this later when it eg needs to be deleted
b.cache.Add(cFileUpload+fi.NativeID, res.ID)
return nil
}
func (b *Bdiscord) handleUploadFileFromURL(msg *config.Message, channelID string, fi *config.FileInfo) error {
_, err := b.c.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{
Content: fi.URL,
AllowedMentions: b.getAllowedMentions(),
})
return err
}

View File

@ -69,33 +69,63 @@ func (b *Bdiscord) webhookSendTextOnly(msg *config.Message, channelID string) (s
func (b *Bdiscord) webhookSendFilesOnly(msg *config.Message, channelID string) error { func (b *Bdiscord) webhookSendFilesOnly(msg *config.Message, channelID string) error {
for _, f := range msg.Extra["file"] { for _, f := range msg.Extra["file"] {
fi := f.(config.FileInfo) //nolint:forcetypeassert fi := f.(config.FileInfo) //nolint:forcetypeassert
file := discordgo.File{ var err error
Name: fi.Name,
ContentType: "", if fi.URL != "" {
Reader: bytes.NewReader(*fi.Data), err = b.webhookSendFileFromURL(msg, channelID, &fi)
} } else if fi.Data != nil {
content := fi.Comment err = b.webhookSendFileFromData(msg, channelID, &fi)
} else {
b.Log.Errorf("Attachment %#v for message %#v had neither Data nor URL", fi, msg)
}
// Cannot use the resulting ID for any edits anyway, so throw it away.
// This has to be re-enabled when we implement message deletion.
_, err := b.transmitter.Send(
channelID,
&discordgo.WebhookParams{
Username: msg.Username,
AvatarURL: msg.Avatar,
Files: []*discordgo.File{&file},
Content: content,
AllowedMentions: b.getAllowedMentions(),
},
)
if err != nil { if err != nil {
b.Log.Errorf("Could not send file %#v for message %#v: %s", file, msg, err) b.Log.Errorf("Could not send attachment %#v for message %#v: %s", fi, msg, err)
return err return err
} }
} }
return nil return nil
} }
func (b *Bdiscord) webhookSendFileFromData(msg *config.Message, channelID string, fi *config.FileInfo) error {
file := discordgo.File{
Name: fi.Name,
ContentType: "",
Reader: bytes.NewReader(*fi.Data),
}
content := fi.Comment
// Cannot use the resulting ID for any edits anyway, so throw it away.
// This has to be re-enabled when we implement message deletion.
_, err := b.transmitter.Send(
channelID,
&discordgo.WebhookParams{
Username: msg.Username,
AvatarURL: msg.Avatar,
Files: []*discordgo.File{&file},
Content: content,
AllowedMentions: b.getAllowedMentions(),
},
)
return err
}
func (b *Bdiscord) webhookSendFileFromURL(msg *config.Message, channelID string, fi *config.FileInfo) error {
// discord client will display any file url as an inline embed,
// without us having to do anything special.
_, err := b.transmitter.Send(
channelID,
&discordgo.WebhookParams{
Content: fi.URL,
Username: msg.Username,
AvatarURL: msg.Avatar,
AllowedMentions: b.getAllowedMentions(),
},
)
return err
}
// webhookSend send one or more message via webhook, taking care of file // webhookSend send one or more message via webhook, taking care of file
// uploads (from slack, telegram or mattermost). // uploads (from slack, telegram or mattermost).
// Returns messageID and error. // Returns messageID and error.