mautrix-discord/attachments.go

136 lines
3 KiB
Go
Raw Normal View History

package main
import (
"bytes"
2022-07-03 09:58:57 +00:00
"fmt"
"image"
2022-05-28 20:03:24 +00:00
"io"
"net/http"
"strings"
2023-01-27 23:57:44 +00:00
"time"
2022-07-03 09:58:57 +00:00
"github.com/bwmarrin/discordgo"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/appservice"
2023-01-27 23:57:44 +00:00
"maunium.net/go/mautrix/crypto/attachment"
"maunium.net/go/mautrix/event"
2023-01-27 23:57:44 +00:00
"go.mau.fi/mautrix-discord/database"
)
2023-01-27 23:57:44 +00:00
func downloadDiscordAttachment(url string) ([]byte, error) {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
2022-05-28 20:03:24 +00:00
for key, value := range discordgo.DroidDownloadHeaders {
req.Header.Set(key, value)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
2022-07-03 09:58:57 +00:00
if resp.StatusCode > 300 {
data, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, data)
}
2022-05-28 20:03:24 +00:00
return io.ReadAll(resp.Body)
}
2022-06-28 08:55:36 +00:00
func (portal *Portal) downloadMatrixAttachment(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 {
return nil, err
}
data, err := portal.MainIntent().DownloadBytes(mxc)
if err != nil {
return nil, err
}
if file != nil {
err = file.DecryptInPlace(data)
if err != nil {
return nil, err
}
}
return data, nil
}
2023-01-27 23:57:44 +00:00
func (br *DiscordBridge) uploadMatrixAttachment(intent *appservice.IntentAPI, data []byte, url string, encrypt bool, attachmentID, mime string) (*database.File, error) {
dbFile := br.DB.File.New()
dbFile.Timestamp = time.Now()
dbFile.URL = url
dbFile.ID = attachmentID
dbFile.Size = len(data)
if strings.HasPrefix(mime, "image/") {
2022-07-03 09:58:57 +00:00
cfg, _, _ := image.DecodeConfig(bytes.NewReader(data))
2023-01-27 23:57:44 +00:00
dbFile.Width = cfg.Width
dbFile.Height = cfg.Height
2022-07-03 09:58:57 +00:00
}
2023-01-27 23:57:44 +00:00
uploadMime := mime
if encrypt {
dbFile.Encrypted = true
dbFile.DecryptionInfo = attachment.NewEncryptedFile()
dbFile.DecryptionInfo.EncryptInPlace(data)
2022-07-03 09:58:57 +00:00
uploadMime = "application/octet-stream"
}
req := mautrix.ReqUploadMedia{
ContentBytes: data,
2022-07-03 09:58:57 +00:00
ContentType: uploadMime,
}
2023-01-27 23:57:44 +00:00
if br.Config.Homeserver.AsyncMedia {
resp, err := intent.UnstableCreateMXC()
if err != nil {
2023-01-27 23:57:44 +00:00
return nil, err
}
2023-01-27 23:57:44 +00:00
dbFile.MXC = resp.ContentURI
req.UnstableMXC = resp.ContentURI
req.UploadURL = resp.UploadURL
go func() {
_, err = intent.UploadMedia(req)
if err != nil {
br.Log.Errorfln("Failed to upload %s: %v", req.UnstableMXC, err)
dbFile.Delete()
}
}()
} else {
uploaded, err := intent.UploadMedia(req)
if err != nil {
2023-01-27 23:57:44 +00:00
return nil, err
}
2023-01-27 23:57:44 +00:00
dbFile.MXC = uploaded.ContentURI
}
2023-01-27 23:57:44 +00:00
dbFile.Insert(nil)
return dbFile, nil
}
2023-01-27 23:57:44 +00:00
func (br *DiscordBridge) copyAttachmentToMatrix(intent *appservice.IntentAPI, url string, encrypt bool, attachmentID, mime string) (*database.File, error) {
dbFile := br.DB.File.Get(url, encrypt)
if dbFile == nil {
data, err := downloadDiscordAttachment(url)
if err != nil {
return nil, err
2022-07-03 09:58:57 +00:00
}
2023-01-27 23:57:44 +00:00
dbFile, err = br.uploadMatrixAttachment(intent, data, url, encrypt, attachmentID, mime)
if err != nil {
return nil, err
}
}
return dbFile, nil
}