converter: handle link previews TG -> Matrix
Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
@@ -84,7 +84,7 @@ func (tc *TelegramConnector) Download(ctx context.Context, mediaID networkid.Med
|
||||
var mimeType string
|
||||
switch media := media.(type) {
|
||||
case *tg.MessageMediaPhoto:
|
||||
data, mimeType, err = download.DownloadPhoto(ctx, client.client.API(), media)
|
||||
data, mimeType, err = download.DownloadPhotoMedia(ctx, client.client.API(), media)
|
||||
case *tg.MessageMediaDocument:
|
||||
document, ok := media.Document.(*tg.Document)
|
||||
if !ok {
|
||||
@@ -98,7 +98,6 @@ func (tc *TelegramConnector) Download(ctx context.Context, mediaID networkid.Med
|
||||
// case *tg.MessageMediaContact: // messageMediaContact#70322949
|
||||
// case *tg.MessageMediaUnsupported: // messageMediaUnsupported#9f84f49e
|
||||
// case *tg.MessageMediaDocument: // messageMediaDocument#4cf4d72d
|
||||
// case *tg.MessageMediaWebPage: // messageMediaWebPage#ddf10c3b
|
||||
// case *tg.MessageMediaVenue: // messageMediaVenue#2ec0533f
|
||||
// case *tg.MessageMediaGame: // messageMediaGame#fdb19008
|
||||
// case *tg.MessageMediaInvoice: // messageMediaInvoice#f6a548d3
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/gotd/td/tg"
|
||||
)
|
||||
|
||||
func getLargestPhotoSize(sizes []tg.PhotoSizeClass) (largest tg.PhotoSizeClass) {
|
||||
func GetLargestPhotoSize(sizes []tg.PhotoSizeClass) (largest tg.PhotoSizeClass) {
|
||||
var maxSize int
|
||||
for _, s := range sizes {
|
||||
var currentSize int
|
||||
@@ -35,17 +35,8 @@ func getLargestPhotoSize(sizes []tg.PhotoSizeClass) (largest tg.PhotoSizeClass)
|
||||
return
|
||||
}
|
||||
|
||||
func DownloadPhoto(ctx context.Context, client downloader.Client, media *tg.MessageMediaPhoto) (data []byte, mimeType string, err error) {
|
||||
p, ok := media.GetPhoto()
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("photo message sent without a photo")
|
||||
}
|
||||
photo, ok := p.(*tg.Photo)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("unrecognized photo type %T", p)
|
||||
}
|
||||
|
||||
largest := getLargestPhotoSize(photo.GetSizes())
|
||||
func DownloadPhoto(ctx context.Context, client downloader.Client, photo *tg.Photo) (data []byte, mimeType string, err error) {
|
||||
largest := GetLargestPhotoSize(photo.GetSizes())
|
||||
file := tg.InputPhotoFileLocation{
|
||||
ID: photo.GetID(),
|
||||
AccessHash: photo.GetAccessHash(),
|
||||
@@ -81,3 +72,15 @@ func DownloadPhoto(ctx context.Context, client downloader.Client, media *tg.Mess
|
||||
}
|
||||
return buf.Bytes(), mimeType, nil
|
||||
}
|
||||
|
||||
func DownloadPhotoMedia(ctx context.Context, client downloader.Client, media *tg.MessageMediaPhoto) (data []byte, mimeType string, err error) {
|
||||
p, ok := media.GetPhoto()
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("photo message sent without a photo")
|
||||
}
|
||||
photo, ok := p.(*tg.Photo)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("unrecognized photo type %T", p)
|
||||
}
|
||||
return DownloadPhoto(ctx, client, photo)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package msgconv
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/gotd/td/tg"
|
||||
@@ -26,33 +27,105 @@ type ttlable interface {
|
||||
GetTTLSeconds() (value int, ok bool)
|
||||
}
|
||||
|
||||
func mediaRequiringUpload(media tg.MessageMediaClass) bool {
|
||||
allowed := []uint32{
|
||||
tg.MessageMediaPhotoTypeID,
|
||||
tg.MessageMediaGeoTypeID,
|
||||
tg.MessageMediaContactTypeID,
|
||||
tg.MessageMediaDocumentTypeID,
|
||||
tg.MessageMediaStoryTypeID,
|
||||
}
|
||||
return slices.Contains(allowed, media.TypeID())
|
||||
}
|
||||
|
||||
func (mc *MessageConverter) ToMatrix(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, msg *tg.Message) (*bridgev2.ConvertedMessage, error) {
|
||||
log := zerolog.Ctx(ctx).With().Str("conversion_direction", "to_matrix").Logger()
|
||||
ctx = log.WithContext(ctx)
|
||||
|
||||
cm := &bridgev2.ConvertedMessage{}
|
||||
if msg.Message != "" {
|
||||
if len(msg.Message) > 0 {
|
||||
var linkPreviews []*event.BeeperLinkPreview
|
||||
if media, ok := msg.GetMedia(); ok && media.TypeID() == tg.MessageMediaWebPageTypeID {
|
||||
preview, err := mc.webpageToBeeperLinkPreview(ctx, intent, media)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if preview != nil {
|
||||
linkPreviews = append(linkPreviews, preview)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO formatting
|
||||
cm.Parts = append(cm.Parts, &bridgev2.ConvertedMessagePart{
|
||||
ID: networkid.PartID("caption"),
|
||||
Type: event.EventMessage,
|
||||
Content: &event.MessageEventContent{MsgType: event.MsgText, Body: msg.Message},
|
||||
ID: networkid.PartID("caption"),
|
||||
Type: event.EventMessage,
|
||||
Content: &event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: msg.Message,
|
||||
BeeperLinkPreviews: linkPreviews,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if media, ok := msg.GetMedia(); ok {
|
||||
mediaParts, disappearingSetting, err := mc.convertMedia(ctx, portal, intent, msg.ID, media)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
switch {
|
||||
case mediaRequiringUpload(media):
|
||||
mediaParts, disappearingSetting, err := mc.convertMediaRequiringUpload(ctx, portal, intent, msg.ID, media)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if disappearingSetting != nil {
|
||||
cm.Disappear = *disappearingSetting
|
||||
}
|
||||
cm.Parts = append(cm.Parts, mediaParts)
|
||||
}
|
||||
if disappearingSetting != nil {
|
||||
cm.Disappear = *disappearingSetting
|
||||
}
|
||||
cm.Parts = append(cm.Parts, mediaParts)
|
||||
}
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
func (mc *MessageConverter) convertMedia(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, msgID int, media tg.MessageMediaClass) (*bridgev2.ConvertedMessagePart, *database.DisappearingSetting, error) {
|
||||
func (mc *MessageConverter) webpageToBeeperLinkPreview(ctx context.Context, intent bridgev2.MatrixAPI, media tg.MessageMediaClass) (*event.BeeperLinkPreview, error) {
|
||||
webpage, ok := media.(*tg.MessageMediaWebPage).Webpage.(*tg.WebPage)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
preview := &event.BeeperLinkPreview{
|
||||
MatchedURL: webpage.URL,
|
||||
LinkPreview: event.LinkPreview{
|
||||
Title: webpage.Title,
|
||||
CanonicalURL: webpage.URL,
|
||||
Description: webpage.Description,
|
||||
},
|
||||
}
|
||||
|
||||
if pc, ok := webpage.GetPhoto(); ok && pc.TypeID() == tg.PhotoTypeID {
|
||||
photo := pc.(*tg.Photo)
|
||||
for _, s := range photo.GetSizes() {
|
||||
switch size := s.(type) {
|
||||
case *tg.PhotoCachedSize:
|
||||
preview.ImageWidth = size.GetW()
|
||||
preview.ImageHeight = size.GetH()
|
||||
case *tg.PhotoSizeProgressive:
|
||||
preview.ImageWidth = size.GetW()
|
||||
preview.ImageHeight = size.GetH()
|
||||
}
|
||||
}
|
||||
|
||||
data, mimeType, err := download.DownloadPhoto(ctx, mc.client.API(), photo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
preview.ImageSize = len(data)
|
||||
preview.ImageType = mimeType
|
||||
|
||||
preview.ImageURL, preview.ImageEncryption, err = intent.UploadMedia(ctx, "", data, "", mimeType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return preview, nil
|
||||
}
|
||||
|
||||
func (mc *MessageConverter) convertMediaRequiringUpload(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, msgID int, media tg.MessageMediaClass) (*bridgev2.ConvertedMessagePart, *database.DisappearingSetting, error) {
|
||||
var partID networkid.PartID
|
||||
var msgType event.MessageType
|
||||
var filename string
|
||||
@@ -97,7 +170,6 @@ func (mc *MessageConverter) convertMedia(ctx context.Context, portal *bridgev2.P
|
||||
// case *tg.MessageMediaGeo: // messageMediaGeo#56e0d474
|
||||
// case *tg.MessageMediaContact: // messageMediaContact#70322949
|
||||
// case *tg.MessageMediaUnsupported: // messageMediaUnsupported#9f84f49e
|
||||
// case *tg.MessageMediaWebPage: // messageMediaWebPage#ddf10c3b
|
||||
// case *tg.MessageMediaVenue: // messageMediaVenue#2ec0533f
|
||||
// case *tg.MessageMediaGame: // messageMediaGame#fdb19008
|
||||
// case *tg.MessageMediaInvoice: // messageMediaInvoice#f6a548d3
|
||||
@@ -146,7 +218,7 @@ func (mc *MessageConverter) convertMedia(ctx context.Context, portal *bridgev2.P
|
||||
filename = "image" + exmime.ExtensionFromMimetype(mimeType)
|
||||
}
|
||||
|
||||
data, mimeType, err = download.DownloadPhoto(ctx, mc.client.API(), media)
|
||||
data, mimeType, err = download.DownloadPhotoMedia(ctx, mc.client.API(), media)
|
||||
case *tg.MessageMediaDocument:
|
||||
document, ok := media.Document.(*tg.Document)
|
||||
if !ok {
|
||||
@@ -160,7 +232,6 @@ func (mc *MessageConverter) convertMedia(ctx context.Context, portal *bridgev2.P
|
||||
// case *tg.MessageMediaGeo: // messageMediaGeo#56e0d474
|
||||
// case *tg.MessageMediaContact: // messageMediaContact#70322949
|
||||
// case *tg.MessageMediaUnsupported: // messageMediaUnsupported#9f84f49e
|
||||
// case *tg.MessageMediaWebPage: // messageMediaWebPage#ddf10c3b
|
||||
// case *tg.MessageMediaVenue: // messageMediaVenue#2ec0533f
|
||||
// case *tg.MessageMediaGame: // messageMediaGame#fdb19008
|
||||
// case *tg.MessageMediaInvoice: // messageMediaInvoice#f6a548d3
|
||||
|
||||
Reference in New Issue
Block a user