From 1c2dc8e9da3696ff2ae1f04541e1960c85c14a71 Mon Sep 17 00:00:00 2001 From: Gary Kramlich Date: Sat, 19 Feb 2022 07:37:12 -0600 Subject: [PATCH] Implement attachments for Matrix -> Discord --- bridge/attachments.go | 35 +++++++++++++++++++++++++++++++++++ bridge/portal.go | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/bridge/attachments.go b/bridge/attachments.go index 47e6452..206cf6e 100644 --- a/bridge/attachments.go +++ b/bridge/attachments.go @@ -11,6 +11,7 @@ import ( "maunium.net/go/mautrix/appservice" "maunium.net/go/mautrix/event" + "maunium.net/go/mautrix/id" ) func (p *Portal) downloadDiscordAttachment(url string) ([]byte, error) { @@ -40,6 +41,40 @@ func (p *Portal) downloadDiscordAttachment(url string) ([]byte, error) { return ioutil.ReadAll(resp.Body) } +func (p *Portal) downloadMatrixAttachment(eventID id.EventID, content *event.MessageEventContent) ([]byte, error) { + var file *event.EncryptedFileInfo + rawMXC := content.URL + + if content.File != nil { + file = content.File + rawMXC = file.URL + } + + mxc, err := rawMXC.Parse() + if err != nil { + p.log.Errorln("Malformed content URL in %s: %v", eventID, err) + + return nil, err + } + + data, err := p.MainIntent().DownloadBytes(mxc) + if err != nil { + p.log.Errorfln("Failed to download media in %s: %v", eventID, err) + + return nil, err + } + + if file != nil { + data, err = file.Decrypt(data) + if err != nil { + p.log.Errorfln("Failed to decrypt media in %s: %v", eventID, err) + return nil, err + } + } + + return data, nil +} + func (p *Portal) uploadMatrixAttachment(intent *appservice.IntentAPI, data []byte, content *event.MessageEventContent) error { uploaded, err := intent.UploadBytes(data, content.Info.MimeType) if err != nil { diff --git a/bridge/portal.go b/bridge/portal.go index 896d1d7..4f60d67 100644 --- a/bridge/portal.go +++ b/bridge/portal.go @@ -1,6 +1,7 @@ package bridge import ( + "bytes" "fmt" "strings" "sync" @@ -592,14 +593,47 @@ func (p *Portal) handleMatrixMessage(sender *User, evt *event.Event) { return } } - } else { - msg, err := sender.Session.ChannelMessageSend(p.Key.ChannelID, content.Body) + + return + } + + var msg *discordgo.Message + var err error + + switch content.MsgType { + case event.MsgText, event.MsgEmote, event.MsgNotice: + msg, err = sender.Session.ChannelMessageSend(p.Key.ChannelID, content.Body) + case event.MsgAudio, event.MsgFile, event.MsgImage, event.MsgVideo: + data, err := p.downloadMatrixAttachment(evt.ID, content) if err != nil { - p.log.Errorfln("Failed to send message: %v", err) + p.log.Errorfln("Failed to download matrix attachment: %v", err) return } + msgSend := &discordgo.MessageSend{ + Files: []*discordgo.File{ + &discordgo.File{ + Name: content.Body, + ContentType: content.Info.MimeType, + Reader: bytes.NewReader(data), + }, + }, + } + + msg, err = sender.Session.ChannelMessageSendComplex(p.Key.ChannelID, msgSend) + default: + p.log.Warnln("unknown message type:", content.MsgType) + return + } + + if err != nil { + p.log.Errorfln("Failed to send message: %v", err) + + return + } + + if msg != nil { dbMsg := p.bridge.db.Message.New() dbMsg.Channel = p.Key dbMsg.DiscordID = msg.ID