diff --git a/go.mod b/go.mod index cd0a3b3..562eb5a 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/stretchr/testify v1.8.1 github.com/yuin/goldmark v1.5.3 maunium.net/go/maulogger/v2 v2.3.2 - maunium.net/go/mautrix v0.13.1-0.20230127212324-870a2cfb9406 + maunium.net/go/mautrix v0.13.1-0.20230128124647-7d98a9f8e3a6 ) require ( diff --git a/go.sum b/go.sum index 7ff060f..2c524ad 100644 --- a/go.sum +++ b/go.sum @@ -75,5 +75,5 @@ maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= maunium.net/go/maulogger/v2 v2.3.2 h1:1XmIYmMd3PoQfp9J+PaHhpt80zpfmMqaShzUTC7FwY0= maunium.net/go/maulogger/v2 v2.3.2/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A= -maunium.net/go/mautrix v0.13.1-0.20230127212324-870a2cfb9406 h1:b3RgrN/RYTW643k+DJfeaonTiOTK+Pxfg2sTEGzpFow= -maunium.net/go/mautrix v0.13.1-0.20230127212324-870a2cfb9406/go.mod h1:gYMQPsZ9lQpyKlVp+DGwOuc9LIcE/c8GZW2CvKHISgM= +maunium.net/go/mautrix v0.13.1-0.20230128124647-7d98a9f8e3a6 h1:c2HKxT3wYxWS213BXaWDY3UkHGfXGmhzOv4h1OKZm20= +maunium.net/go/mautrix v0.13.1-0.20230128124647-7d98a9f8e3a6/go.mod h1:gYMQPsZ9lQpyKlVp+DGwOuc9LIcE/c8GZW2CvKHISgM= diff --git a/portal.go b/portal.go index 406b1b6..24c733d 100644 --- a/portal.go +++ b/portal.go @@ -14,6 +14,7 @@ import ( "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/crypto/attachment" "maunium.net/go/mautrix/format" + "maunium.net/go/mautrix/util" "maunium.net/go/mautrix/util/variationselector" "github.com/bwmarrin/discordgo" @@ -58,10 +59,14 @@ type Portal struct { discordMessages chan portalDiscordMessage matrixMessages chan portalMatrixMessage + recentMessages *util.RingBuffer[string, *discordgo.Message] + currentlyTyping []id.UserID currentlyTypingLock sync.Mutex } +const recentMessageBufferSize = 32 + var _ bridge.Portal = (*Portal)(nil) var _ bridge.ReadReceiptHandlingPortal = (*Portal)(nil) var _ bridge.MembershipHandlingPortal = (*Portal)(nil) @@ -226,6 +231,8 @@ func (br *DiscordBridge) NewPortal(dbPortal *database.Portal) *Portal { discordMessages: make(chan portalDiscordMessage, br.Config.Bridge.PortalMessageBuffer), matrixMessages: make(chan portalMatrixMessage, br.Config.Bridge.PortalMessageBuffer), + + recentMessages: util.NewRingBuffer[string, *discordgo.Message](recentMessageBufferSize), } go portal.messageLoop() @@ -931,6 +938,8 @@ func (portal *Portal) handleDiscordMessageCreate(user *User, msg *discordgo.Mess return } + portal.recentMessages.Push(msg.ID, msg) + // Handle normal message existing := portal.bridge.DB.Message.GetByDiscordID(portal.Key, msg.ID) if existing != nil { @@ -1085,12 +1094,25 @@ func (portal *Portal) handleDiscordMessageUpdate(user *User, msg *discordgo.Mess } if msg.Author == nil { - if len(msg.Embeds) > 0 { - portal.log.Debugln("ignoring update for opengraph attachment") - + creationMessage, ok := portal.recentMessages.Get(msg.ID) + if !ok { + portal.log.Debugfln("Dropping edit with no author of non-recent message %s", msg.ID) return } - return + portal.log.Debugfln("Found original message %s in cache for edit without author", msg.ID) + if len(msg.Embeds) > 0 { + creationMessage.Embeds = msg.Embeds + } + if len(msg.Attachments) > 0 { + creationMessage.Attachments = msg.Attachments + } + if len(msg.Components) > 0 { + creationMessage.Components = msg.Components + } + // TODO are there other fields that need copying? + msg = creationMessage + } else { + portal.recentMessages.Replace(msg.ID, msg) } intent := portal.bridge.GetPuppetByID(msg.Author.ID).IntentFor(portal) @@ -1123,7 +1145,18 @@ func (portal *Portal) handleDiscordMessageUpdate(user *User, msg *discordgo.Mess portal.log.Debugfln("Dropping non-text edit to %s (message on matrix: %t, text on discord: %t)", msg.ID, existing[0].AttachmentID == "", len(msg.Content) > 0) return } - content := portal.renderDiscordMarkdown(msg.Content) + var content event.MessageEventContent + var extraContent map[string]any + if isPlainGifMessage(msg) { + converted := portal.convertDiscordVideoEmbed(intent, msg.Embeds[0]) + content = *converted.Content + extraContent = converted.Extra + } else { + content = portal.renderDiscordMarkdown(msg.Content) + extraContent = map[string]any{ + "com.beeper.linkpreviews": portal.convertDiscordLinkEmbedsToBeeper(intent, msg.Embeds), + } + } content.SetEdit(existing[0].MXID) var editTS int64 @@ -1131,7 +1164,7 @@ func (portal *Portal) handleDiscordMessageUpdate(user *User, msg *discordgo.Mess editTS = msg.EditedTimestamp.UnixMilli() } // TODO figure out some way to deduplicate outgoing edits - resp, err := portal.sendMatrixMessage(intent, event.EventMessage, &content, nil, editTS) + resp, err := portal.sendMatrixMessage(intent, event.EventMessage, &content, extraContent, editTS) if err != nil { portal.log.Warnfln("Failed to send message %s to matrix: %v", msg.ID, err) return