Skip to content

Commit

Permalink
Implement discord webhooks message splitting
Browse files Browse the repository at this point in the history
  • Loading branch information
BenWiederhake committed Mar 7, 2024
1 parent 8a646c5 commit aa247d2
Showing 1 changed file with 55 additions and 32 deletions.
87 changes: 55 additions & 32 deletions bridge/discord/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bdiscord

import (
"bytes"
"strings"

"github.com/42wim/matterbridge/bridge/config"
"github.com/42wim/matterbridge/bridge/helper"
Expand Down Expand Up @@ -45,11 +46,12 @@ func (b *Bdiscord) maybeGetLocalAvatar(msg *config.Message) string {
// webhookSend send one or more message via webhook, taking care of file
// uploads (from slack, telegram or mattermost).
// Returns messageID and error.
func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordgo.Message, error) {
func (b *Bdiscord) webhookSend(msg *config.Message, channelID string, clippingMessage string, splitMax int) (string, error) {

Check failure on line 49 in bridge/discord/webhook.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Function 'webhookSend' is too long (73 > 60) (funlen)
var (
res *discordgo.Message
res string = ""
res2 *discordgo.Message
err error
err2 error
)

// If avatar is unset, mutate the message to include the local avatar (but only if settings say we should do this)
Expand All @@ -61,17 +63,28 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg

// We can't send empty messages.
if msg.Text != "" {
res, err = b.transmitter.Send(
channelID,
&discordgo.WebhookParams{
Content: msg.Text,
Username: msg.Username,
AvatarURL: msg.Avatar,
AllowedMentions: b.getAllowedMentions(),
},
)
if err != nil {
b.Log.Errorf("Could not send text (%s) for message %#v: %s", msg.Text, msg, err)
msgParts := helper.ClipOrSplitMessage(msg.Text, MessageLength, clippingMessage, splitMax)
var msgIds = []string{}

Check failure on line 67 in bridge/discord/webhook.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gofumpt`-ed (gofumpt)
for _, msgPart := range msgParts {
partialRes, partialErr := b.transmitter.Send(
channelID,
&discordgo.WebhookParams{
Content: msgPart,
Username: msg.Username,
AvatarURL: msg.Avatar,
AllowedMentions: b.getAllowedMentions(),
},
)
if partialErr != nil {
err = partialErr
break
} else {
msgIds = append(msgIds, partialRes.ID)
}
}
// Exploit that a discord message ID is actually just a large number, so we encode a list of IDs by separating them with ";".
if err == nil {
res = strings.Join(msgIds, ";")
}
}

Expand All @@ -85,7 +98,7 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
}
content := fi.Comment

res2, err = b.transmitter.Send(
res2, err2 = b.transmitter.Send(
channelID,
&discordgo.WebhookParams{
Username: msg.Username,
Expand All @@ -95,14 +108,15 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
AllowedMentions: b.getAllowedMentions(),
},
)
if err != nil {
if err2 != nil {
err = err2
b.Log.Errorf("Could not send file %#v for message %#v: %s", file, msg, err)
}
}
}

if msg.Text == "" {
res = res2
res = res2.ID
}

return res, err
Expand All @@ -120,35 +134,44 @@ func (b *Bdiscord) handleEventWebhook(msg *config.Message, channelID string) (st
return "", nil
}

msg.Text = helper.ClipMessage(msg.Text, MessageLength, b.GetString("MessageClipped"))
msg.Text = b.replaceUserMentions(msg.Text)
// discord username must be [0..32] max
if len(msg.Username) > 32 {
msg.Username = msg.Username[0:32]
}

if msg.ID != "" {
// Exploit that a discord message ID is actually just a large number, and we encode a list of IDs by separating them with ";".
var msgIds = strings.Split(msg.ID, ";")

Check failure on line 144 in bridge/discord/webhook.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gofumpt`-ed (gofumpt)
msgParts := helper.ClipOrSplitMessage(b.replaceUserMentions(msg.Text), MessageLength, b.GetString("MessageClipped"), len(msgIds))
for len(msgParts) < len(msgIds) {
msgParts = append(msgParts, "((obsoleted by edit))")
}
b.Log.Debugf("Editing webhook message")
err := b.transmitter.Edit(channelID, msg.ID, &discordgo.WebhookParams{
Content: msg.Text,
Username: msg.Username,
AllowedMentions: b.getAllowedMentions(),
})
if err == nil {
var edit_err error = nil
for i := range msgParts {
// In case of split-messages where some parts remain the same (i.e. only a typo-fix in a huge message), this causes some noop-updates.
// TODO: Optimize away noop-updates of un-edited messages
edit_err = b.transmitter.Edit(channelID, msgIds[i], &discordgo.WebhookParams{
Content: msgParts[i],
Username: msg.Username,
AllowedMentions: b.getAllowedMentions(),
})
if edit_err != nil {
break
}
}
if edit_err == nil {
return msg.ID, nil
}
b.Log.Errorf("Could not edit webhook message: %s", err)
b.Log.Errorf("Could not edit webhook message(s): %s; sending as new message(s) instead", edit_err)
}

b.Log.Debugf("Processing webhook sending for message %#v", msg)
discordMsg, err := b.webhookSend(msg, channelID)
msg.Text = b.replaceUserMentions(msg.Text)
msgId, err := b.webhookSend(msg, channelID, b.GetString("MessageClipped"), b.GetInt("MessageSplitMaxCount"))
if err != nil {
b.Log.Errorf("Could not broadcast via webhook for message %#v: %s", msg, err)
b.Log.Errorf("Could not broadcast via webhook for message %#v: %s", msgId, err)
return "", err
}
if discordMsg == nil {
return "", nil
}

return discordMsg.ID, nil
return msgId, nil
}

0 comments on commit aa247d2

Please sign in to comment.