fix: sync sticker material reuse handling
This commit is contained in:
parent
bb07eb16d1
commit
20b388eeaa
5 changed files with 370 additions and 44 deletions
142
internal/app/files/sticker_material.go
Normal file
142
internal/app/files/sticker_material.go
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
package files
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
stickerMaterialMimeTGS = "application/x-tgsticker"
|
||||
stickerMaterialMimeWebP = "image/webp"
|
||||
stickerMaterialMimeWebM = "video/webm"
|
||||
stickerMaterialMimeMP4 = "video/mp4"
|
||||
stickerMaterialMimeJSON = "application/json"
|
||||
stickerMaterialMimeOctet = "application/octet-stream"
|
||||
)
|
||||
|
||||
func normalizeStickerMaterialDocumentMIME(doc domain.Document) (domain.Document, bool) {
|
||||
mimeType := canonicalStickerMaterialMime(doc.StickerSetMaterialMime())
|
||||
if mimeType == "" || mimeType == stickerMaterialMimeJSON {
|
||||
return doc, false
|
||||
}
|
||||
if !shouldReplaceStickerMaterialMime(doc.MimeType, mimeType) {
|
||||
return doc, false
|
||||
}
|
||||
doc.MimeType = mimeType
|
||||
return doc, true
|
||||
}
|
||||
|
||||
func (s *Service) materialDocumentForStickerSet(ctx context.Context, doc domain.Document, targetSetID int64) (domain.Document, error) {
|
||||
if ownedSetID, _, ok := doc.StickerSetRef(); ok && ownedSetID != 0 && ownedSetID != targetSetID {
|
||||
return s.cloneStickerSetDocument(ctx, doc)
|
||||
}
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
func (s *Service) cloneStickerSetDocument(ctx context.Context, source domain.Document) (domain.Document, error) {
|
||||
copied := copyDocuments([]domain.Document{source})
|
||||
if len(copied) == 0 {
|
||||
return domain.Document{}, domain.ErrStickerSetFileInvalid
|
||||
}
|
||||
clone := copied[0]
|
||||
oldID := clone.ID
|
||||
clone.ID = randomID()
|
||||
clone.AccessHash = randomID()
|
||||
clone.FileReference = randomFileReference()
|
||||
|
||||
if source.Size > 0 {
|
||||
blob, found, err := s.media.GetFileBlob(ctx, fmt.Sprintf("doc:%d", oldID))
|
||||
if err != nil {
|
||||
return domain.Document{}, err
|
||||
}
|
||||
if !found {
|
||||
return domain.Document{}, domain.ErrStickerSetFileInvalid
|
||||
}
|
||||
blob.LocationKey = fmt.Sprintf("doc:%d", clone.ID)
|
||||
if normalized, changed := normalizeStickerMaterialDocumentMIME(clone); changed {
|
||||
clone = normalized
|
||||
}
|
||||
if mimeType := canonicalStickerMaterialMime(clone.StickerSetMaterialMime()); mimeType != "" && shouldReplaceStickerMaterialMime(blob.MimeType, mimeType) {
|
||||
blob.MimeType = mimeType
|
||||
}
|
||||
if err := s.media.PutFileBlob(ctx, blob); err != nil {
|
||||
return domain.Document{}, err
|
||||
}
|
||||
s.blobCache.put(blob.LocationKey, blob)
|
||||
}
|
||||
|
||||
for _, thumb := range source.Thumbs {
|
||||
if !thumb.Downloadable() || thumb.Type == "" {
|
||||
continue
|
||||
}
|
||||
oldKey := fmt.Sprintf("doc:%d:%s", oldID, thumb.Type)
|
||||
blob, found, err := s.media.GetFileBlob(ctx, oldKey)
|
||||
if err != nil {
|
||||
return domain.Document{}, err
|
||||
}
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
blob.LocationKey = fmt.Sprintf("doc:%d:%s", clone.ID, thumb.Type)
|
||||
if err := s.media.PutFileBlob(ctx, blob); err != nil {
|
||||
return domain.Document{}, err
|
||||
}
|
||||
s.blobCache.put(blob.LocationKey, blob)
|
||||
}
|
||||
|
||||
return clone, nil
|
||||
}
|
||||
|
||||
func (s *Service) ensureStickerMaterialMIME(ctx context.Context, doc domain.Document, mimeType string) (domain.Document, error) {
|
||||
mimeType = canonicalStickerMaterialMime(mimeType)
|
||||
if mimeType == "" || mimeType == stickerMaterialMimeJSON {
|
||||
return doc, nil
|
||||
}
|
||||
if shouldReplaceStickerMaterialMime(doc.MimeType, mimeType) {
|
||||
doc.MimeType = mimeType
|
||||
}
|
||||
if s == nil || s.media == nil || doc.ID == 0 {
|
||||
return doc, nil
|
||||
}
|
||||
blob, found, err := s.media.GetFileBlob(ctx, fmt.Sprintf("doc:%d", doc.ID))
|
||||
if err != nil {
|
||||
return domain.Document{}, err
|
||||
}
|
||||
if found && shouldReplaceStickerMaterialMime(blob.MimeType, mimeType) {
|
||||
blob.MimeType = mimeType
|
||||
if err := s.media.PutFileBlob(ctx, blob); err != nil {
|
||||
return domain.Document{}, err
|
||||
}
|
||||
s.blobCache.put(blob.LocationKey, blob)
|
||||
}
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
func canonicalStickerMaterialMime(mimeType string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(mimeType)) {
|
||||
case stickerMaterialMimeTGS:
|
||||
return stickerMaterialMimeTGS
|
||||
case stickerMaterialMimeWebP:
|
||||
return stickerMaterialMimeWebP
|
||||
case stickerMaterialMimeWebM:
|
||||
return stickerMaterialMimeWebM
|
||||
case stickerMaterialMimeMP4:
|
||||
return stickerMaterialMimeMP4
|
||||
case stickerMaterialMimeJSON, "text/json", "application/lottie+json":
|
||||
return stickerMaterialMimeJSON
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func shouldReplaceStickerMaterialMime(current, inferred string) bool {
|
||||
inferred = canonicalStickerMaterialMime(inferred)
|
||||
if inferred == "" {
|
||||
return false
|
||||
}
|
||||
current = strings.ToLower(strings.TrimSpace(current))
|
||||
return current == "" || current == stickerMaterialMimeOctet
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue