attachments.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package main
  2. import (
  3. "bytes"
  4. "image"
  5. "io"
  6. "net/http"
  7. "strings"
  8. "github.com/bwmarrin/discordgo"
  9. "maunium.net/go/mautrix"
  10. "maunium.net/go/mautrix/appservice"
  11. "maunium.net/go/mautrix/event"
  12. "maunium.net/go/mautrix/id"
  13. )
  14. func (portal *Portal) downloadDiscordAttachment(url string) ([]byte, error) {
  15. // We might want to make this save to disk in the future. Discord defaults
  16. // to 8mb for all attachments to a messages for non-nitro users and
  17. // non-boosted servers.
  18. //
  19. // If the user has nitro classic, their limit goes up to 50mb but if a user
  20. // has regular nitro the limit is increased to 100mb.
  21. //
  22. // Servers boosted to level 2 will have the limit bumped to 50mb.
  23. req, err := http.NewRequest(http.MethodGet, url, nil)
  24. if err != nil {
  25. return nil, err
  26. }
  27. for key, value := range discordgo.DroidDownloadHeaders {
  28. req.Header.Set(key, value)
  29. }
  30. resp, err := http.DefaultClient.Do(req)
  31. if err != nil {
  32. return nil, err
  33. }
  34. defer resp.Body.Close()
  35. return io.ReadAll(resp.Body)
  36. }
  37. func (portal *Portal) downloadMatrixAttachment(eventID id.EventID, content *event.MessageEventContent) ([]byte, error) {
  38. var file *event.EncryptedFileInfo
  39. rawMXC := content.URL
  40. if content.File != nil {
  41. file = content.File
  42. rawMXC = file.URL
  43. }
  44. mxc, err := rawMXC.Parse()
  45. if err != nil {
  46. portal.log.Errorln("Malformed content URL in %s: %v", eventID, err)
  47. return nil, err
  48. }
  49. data, err := portal.MainIntent().DownloadBytes(mxc)
  50. if err != nil {
  51. portal.log.Errorfln("Failed to download media in %s: %v", eventID, err)
  52. return nil, err
  53. }
  54. if file != nil {
  55. err = file.DecryptInPlace(data)
  56. if err != nil {
  57. portal.log.Errorfln("Failed to decrypt media in %s: %v", eventID, err)
  58. return nil, err
  59. }
  60. }
  61. return data, nil
  62. }
  63. func (portal *Portal) uploadMatrixAttachment(intent *appservice.IntentAPI, data []byte, content *event.MessageEventContent) error {
  64. req := mautrix.ReqUploadMedia{
  65. ContentBytes: data,
  66. ContentType: content.Info.MimeType,
  67. }
  68. var mxc id.ContentURI
  69. if portal.bridge.Config.Homeserver.AsyncMedia {
  70. uploaded, err := intent.UnstableUploadAsync(req)
  71. if err != nil {
  72. return err
  73. }
  74. mxc = uploaded.ContentURI
  75. } else {
  76. uploaded, err := intent.UploadMedia(req)
  77. if err != nil {
  78. return err
  79. }
  80. mxc = uploaded.ContentURI
  81. }
  82. content.URL = mxc.CUString()
  83. content.Info.Size = len(data)
  84. if content.Info.Width == 0 && content.Info.Height == 0 && strings.HasPrefix(content.Info.MimeType, "image/") {
  85. cfg, _, _ := image.DecodeConfig(bytes.NewReader(data))
  86. content.Info.Width = cfg.Width
  87. content.Info.Height = cfg.Height
  88. }
  89. return nil
  90. }