diff --git a/bridge/config/config.go b/bridge/config/config.go index 18c60920..75792ed0 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -121,6 +121,7 @@ type Protocol struct { MessageLength int // IRC, max length of a message allowed MessageQueue int // IRC, size of message queue for flood control MessageSplit bool // IRC, split long messages with newlines on MessageLength instead of clipping + MessageSplitMaxCount int // discord, split long messages into at most this many messages instead of clipping (MessageLength=1950 cannot be configured) Muc string // xmpp MxID string // matrix Name string // all protocols diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index 51dbe6bc..5b10226a 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -316,6 +316,7 @@ func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (st // Upload a file if it exists if msg.Extra != nil { for _, rmsg := range helper.HandleExtra(msg, b.General) { + // TODO: Use ClipOrSplitMessage rmsg.Text = helper.ClipMessage(rmsg.Text, MessageLength, b.GetString("MessageClipped")) if _, err := b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text); err != nil { b.Log.Errorf("Could not send message %#v: %s", rmsg, err) @@ -327,35 +328,53 @@ func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (st } } - msg.Text = helper.ClipMessage(msg.Text, MessageLength, b.GetString("MessageClipped")) - msg.Text = b.replaceUserMentions(msg.Text) - // Edit message if msg.ID != "" { - _, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text) - return msg.ID, err - } - - m := discordgo.MessageSend{ - Content: msg.Username + msg.Text, - AllowedMentions: b.getAllowedMentions(), - } - - if msg.ParentValid() { - m.Reference = &discordgo.MessageReference{ - MessageID: msg.ParentID, - ChannelID: channelID, - GuildID: b.guildID, + // 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, ";") + msgParts := helper.ClipOrSplitMessage(b.replaceUserMentions(msg.Text), MessageLength, b.GetString("MessageClipped"), len(msgIds)) + for len(msgParts) < len(msgIds) { + msgParts = append(msgParts, "((obsoleted by edit))") } + 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 + // TODO: Use RemoteNickFormat instead of this broken concatenation + _, err := b.c.ChannelMessageEdit(channelID, msgIds[i], msg.Username+msgParts[i]) + if err != nil { + return "", err + } + } + return msg.ID, nil } - // Post normal message - res, err := b.c.ChannelMessageSendComplex(channelID, &m) - if err != nil { - return "", err + msgParts := helper.ClipOrSplitMessage(b.replaceUserMentions(msg.Text), MessageLength, b.GetString("MessageClipped"), b.GetInt("MessageSplitMaxCount")) + var msgIds = []string{} + + for _, msgPart := range msgParts { + m := discordgo.MessageSend{ + Content: msg.Username + msgPart, + AllowedMentions: b.getAllowedMentions(), + } + + if msg.ParentValid() { + m.Reference = &discordgo.MessageReference{ + MessageID: msg.ParentID, + ChannelID: channelID, + GuildID: b.guildID, + } + } + + // Post normal message + res, err := b.c.ChannelMessageSendComplex(channelID, &m) + if err != nil { + return "", err + } + msgIds = append(msgIds, res.ID) } - return res.ID, nil + // Exploit that a discord message ID is actually just a large number, so we encode a list of IDs by separating them with ";". + return strings.Join(msgIds, ";"), nil } // handleUploadFile handles native upload of files diff --git a/matterbridge.toml.sample b/matterbridge.toml.sample index 5932b269..a3c471f5 100644 --- a/matterbridge.toml.sample +++ b/matterbridge.toml.sample @@ -925,10 +925,17 @@ ShowTopicChange=false # Supported from the following bridges: slack SyncTopic=false -#Message to show when a message is too big -#Default "" +# Message to show when a message is too big +# Default "" MessageClipped="" +# Before clipping, try to split messages into at most this many parts. 0 is treated like 1. +# Be careful with large numbers, as this might cause flooding. +# Example: A maximum telegram message of 4096 bytes is received. This requires 3 Discord +# messages (each capped at a hardcoded 1950 bytes). +# Default 1 +MessageSplitMaxCount=3 + ################################################################### #telegram section ###################################################################