commands/imagepack: include pack metadata in sticker info

This commit is contained in:
Tulir Asokan
2026-04-23 14:26:52 +03:00
parent 7a6d1bf17a
commit 8512cfe6a6
6 changed files with 134 additions and 18 deletions
+99 -11
View File
@@ -57,6 +57,7 @@ import (
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/message"
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/uploader"
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
"go.mau.fi/mautrix-telegram/pkg/gotd/tgerr"
"go.mau.fi/mautrix-telegram/pkg/connector/emojis"
"go.mau.fi/mautrix-telegram/pkg/connector/humanise"
@@ -242,10 +243,90 @@ func (tc *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *brid
return nil
}
func (tc *TelegramClient) transferMediaToTelegram(ctx context.Context, content *event.MessageEventContent, sticker, forceDocument bool) (tg.InputMediaClass, error) {
func (tc *TelegramClient) parseInputPack(meta map[string]any) (shortName string, id, accessHash int64) {
shortName, _ = meta["short_name"].(string)
idStr, _ := meta["id"].(string)
if idStr != "" {
id, _ = strconv.ParseInt(idStr, 10, 64)
}
accessHashStr, _ := meta["access_hash"].(string)
accessHashSourceStr, _ := meta["access_hash_source"].(string)
if id != 0 && accessHashStr != "" && accessHashSourceStr != "" {
accessHashSource, _ := strconv.ParseInt(accessHashSourceStr, 10, 64)
if accessHashSource == tc.telegramUserID {
accessHash, _ = strconv.ParseInt(accessHashStr, 10, 64)
}
}
return
}
func (tc *TelegramClient) findOriginalStickerDocument(ctx context.Context, info map[string]any, forceClearCache bool) (tg.InputMediaClass, error) {
stickerIDStr, ok := info["id"].(string)
if !ok {
return nil, nil
}
stickerID, err := strconv.ParseInt(stickerIDStr, 10, 64)
if err != nil {
return nil, nil
}
pack, ok := info["pack"].(map[string]any)
if !ok {
return nil, nil
}
var inputPack tg.InputStickerSetClass
var cacheKey string
packName, packID, packAccessHash := tc.parseInputPack(pack)
if packAccessHash != 0 {
inputPack = &tg.InputStickerSetID{ID: packID, AccessHash: packAccessHash}
cacheKey = fmt.Sprintf("pack_id:%d", packID)
} else if packName != "" {
inputPack = &tg.InputStickerSetShortName{ShortName: packName}
cacheKey = fmt.Sprintf("pack_name:%s", packName)
} else {
return nil, nil
}
tc.stickerPackCacheLock.Lock()
defer tc.stickerPackCacheLock.Unlock()
docMap, ok := tc.stickerPackCache[cacheKey]
if !ok || forceClearCache {
resp, err := tc.client.API().MessagesGetStickerSet(ctx, &tg.MessagesGetStickerSetRequest{Stickerset: inputPack})
if err != nil {
if tgerr.Is(err, tg.ErrStickersetInvalid) {
tc.stickerPackCache[cacheKey] = nil
}
return nil, fmt.Errorf("failed to get sticker set: %w", err)
}
set, ok := resp.AsModified()
if !ok {
tc.stickerPackCache[cacheKey] = nil
return nil, fmt.Errorf("unexpected response type for MessagesGetStickerSet: %T", resp)
}
docMap = set.MapDocuments().DocumentToMap()
tc.stickerPackCache[cacheKey] = docMap
tc.stickerPackCache[fmt.Sprintf("pack_id:%d", set.Set.ID)] = docMap
tc.stickerPackCache[fmt.Sprintf("pack_name:%s", set.Set.ShortName)] = docMap
}
stickerDoc, ok := docMap[stickerID]
if !ok {
return nil, nil
}
return &tg.InputMediaDocument{ID: stickerDoc.AsInput()}, nil
}
func (tc *TelegramClient) transferMediaToTelegram(ctx context.Context, content *event.MessageEventContent, sticker, forceRetry, forceDocument bool) (tg.InputMediaClass, error) {
var upload tg.InputFileClass
filename := getMediaFilename(content)
info := content.GetInfo()
if sticker {
extra, ok := info.Extra["fi.mau.telegram.sticker"].(map[string]any)
if !ok {
// Not from telegram, continue to reupload
} else if origFile, err := tc.findOriginalStickerDocument(ctx, extra, forceRetry); err != nil {
zerolog.Ctx(ctx).Err(err).Msg("Failed to find original sticker document, falling back to reupload")
} else if origFile != nil {
return origFile, nil
}
}
err := tc.main.Bridge.Bot.DownloadMediaToFile(ctx, content.URL, content.File, false, func(f *os.File) (err error) {
uploadFilename := f.Name()
if sticker && (info.MimeType == "image/png" || info.MimeType == "image/jpeg") {
@@ -458,19 +539,26 @@ func (tc *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2
var updates tg.UpdatesClass
if msg.Event.Type == event.EventSticker {
var media tg.InputMediaClass
media, err = tc.transferMediaToTelegram(ctx, msg.Content, true, false)
if err != nil {
return nil, err
}
updates, err = tc.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{
mediaReq := &tg.MessagesSendMediaRequest{
Peer: peer,
Message: message,
Entities: entities,
Media: media,
ReplyTo: replyTo,
RandomID: randomID,
})
}
mediaReq.Media, err = tc.transferMediaToTelegram(ctx, msg.Content, true, false, false)
if err != nil {
return nil, err
}
updates, err = tc.client.API().MessagesSendMedia(ctx, mediaReq)
if tgerr.Is(err, tg.ErrFileReferenceExpired) {
zerolog.Ctx(ctx).Debug().AnErr("send_error", err).Msg("Trying to refetch sticker pack")
mediaReq.Media, err = tc.transferMediaToTelegram(ctx, msg.Content, true, true, false)
if err != nil {
return nil, err
}
updates, err = tc.client.API().MessagesSendMedia(ctx, mediaReq)
}
} else {
switch msg.Content.MsgType {
case event.MsgText, event.MsgNotice, event.MsgEmote:
@@ -485,7 +573,7 @@ func (tc *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2
case event.MsgImage, event.MsgFile, event.MsgAudio, event.MsgVideo:
var media tg.InputMediaClass
forceDocument, _ := msg.Event.Content.Raw["fi.mau.telegram.force_document"].(bool)
media, err = tc.transferMediaToTelegram(ctx, msg.Content, false, forceDocument)
media, err = tc.transferMediaToTelegram(ctx, msg.Content, false, false, forceDocument)
if err != nil {
return nil, err
}
@@ -650,7 +738,7 @@ func (tc *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Ma
} else {
log.Info().Msg("media URI changed, re-uploading media")
forceDocument, _ := msg.Event.Content.Raw["fi.mau.telegram.force_document"].(bool)
req.Media, err = tc.transferMediaToTelegram(ctx, msg.Content, false, forceDocument)
req.Media, err = tc.transferMediaToTelegram(ctx, msg.Content, false, false, forceDocument)
if err != nil {
return err
}