move gotd fork into repo. (#111)

- update to latest telegram layer
- remove some references to fields in tg.Entities that don't exist in
the schema
- originally added here:
https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e
  - referenced here
-
https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3
-
https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
Adam Van Ymeren
2025-06-27 20:03:37 -07:00
committed by GitHub
parent 0952df0244
commit 7a04f298d2
19264 changed files with 1539697 additions and 84 deletions
+45
View File
@@ -0,0 +1,45 @@
package thumbnail
import (
"strconv"
)
// DecodePath decodes vector thumbnail from thumbnail bytes (e.g. tg.PhotoPathSize with type "j").
//
// See DecodePathTo.
func DecodePath(data []byte) []byte {
return DecodePathTo(data, nil)
}
// DecodePathTo decodes vector thumbnail to given slice.
//
// Returned path will contain the actual SVG path that can
// be directly inserted in the d attribute of an svg <path> element:
//
// <?xml version="1.0" encoding="utf-8"?>
// <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
// viewBox="0 0 512 512" xml:space="preserve">
// <path d="{$path}"/>
// </svg>
//
// See https://core.telegram.org/api/files#vector-thumbnails.
func DecodePathTo(data, to []byte) []byte {
const (
lookup = "AACAAAAHAAALMAAAQASTAVAAAZaacaaaahaaalmaaaqastava.az0123456789-,"
)
to = append(to, 'M')
for _, num := range data {
if num >= 128+64 {
to = append(to, lookup[int(num-128-64)])
} else {
if num >= 128 {
to = append(to, ',')
} else if num >= 64 {
to = append(to, '-')
}
to = strconv.AppendInt(to, int64(num&63), 10)
}
}
to = append(to, 'z')
return to
}
@@ -0,0 +1,44 @@
package thumbnail_test
import (
"os"
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/thumbnail"
)
func ExampleDecodePath() {
thumb := []uint8{
0x1a, 0x00, 0xb2, 0x04, 0xdc, 0x47, 0x03, 0x81, 0x73, 0x55, 0x48, 0x01, 0x46, 0x05, 0x44, 0x45,
0x4f, 0x8b, 0x52, 0x8d, 0x4e, 0x8a, 0x5d, 0x8b, 0x6e, 0x8b, 0x71, 0x81, 0x4c, 0x4d, 0x07, 0x47,
0x50, 0x02, 0x81, 0x46, 0x84, 0x4b, 0x83, 0x50, 0x80, 0x44, 0x67, 0x47, 0x01, 0x6b, 0x47, 0x08,
0x43, 0x44, 0x4f, 0x53, 0x43, 0x56, 0x8e, 0x44, 0x97, 0x94, 0x9d, 0x9c, 0x82, 0x84, 0x89, 0x45,
0x8b, 0x42, 0x88, 0x8a, 0xa6, 0xb3, 0xa8, 0xbc, 0x81, 0x8a, 0x81, 0xad, 0x82, 0xae, 0x87, 0x88,
0xa5, 0x67, 0xab, 0x6a, 0x92, 0x49, 0xaa, 0x42, 0xb6, 0x4e, 0x8d, 0x4e, 0x5e, 0x80, 0x69, 0x43,
0x45, 0x41, 0x4a, 0x46, 0x4d, 0x49, 0x52, 0x51, 0x8a, 0x46, 0x89, 0x47, 0x4b, 0x4f, 0x5f, 0x5b,
0x6d, 0x67, 0x64, 0x5f, 0x46, 0x06, 0x48, 0x08, 0x63, 0x4d, 0x03, 0xa1, 0x70, 0x89, 0x06, 0x81,
0x8b, 0x01, 0x48, 0x87, 0x44, 0x8a, 0x4c, 0x91, 0x51, 0x98, 0x51, 0x87, 0x03, 0x81, 0x89, 0x04,
0x8f, 0x88, 0x86, 0x90, 0x8e, 0x95, 0x97, 0x81, 0x81, 0x82, 0x8b, 0x84, 0x8c, 0x98, 0x8d, 0xb2,
0x93, 0x87, 0x00, 0xa9, 0xab, 0xad, 0x8e, 0x8a, 0x07, 0x69, 0x8c, 0x05, 0x5a, 0x89, 0x75, 0x84,
0x48, 0x00, 0x87, 0x46, 0x80, 0x8c, 0x86, 0x92, 0x86, 0x90, 0x81, 0xa4, 0x4b, 0xb2, 0x81, 0x95,
0x91, 0x9b, 0xab, 0xab, 0xbf, 0x95, 0x99, 0x87, 0x03, 0xb9, 0x87, 0x00, 0x89, 0x04, 0x42, 0xac,
0x4e, 0x04, 0xb5, 0x51, 0x04, 0xb3, 0x4a, 0x81, 0x46, 0x86, 0x4a, 0x8b, 0x41, 0x81, 0x43, 0x44,
0x45, 0x43, 0x51, 0x85, 0x5c, 0x8c, 0x6f, 0x8c,
}
r := thumbnail.DecodePath(thumb)
w := os.Stdout
w.WriteString(`<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<path d="`)
w.Write(r)
w.WriteString(`"/>
</svg>`)
// Output:
// <?xml version="1.0" encoding="utf-8"?>
// <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
// viewBox="0 0 512 512" xml:space="preserve">
// <path d="M260,504c-73,1-51-21-81-65-4-5-15,11-18,13-14,10-29,11-46,11-49,1-12-137-7-162,1-6,4-11,3-16,0-4-39-71-43-78-3-4-15-19-3-22,14-4,23,20,29,28,2,4,9-5,11-2,8,10,38,51,40,60,1,10,1,45,2,46,7,8,37-39,43-42,18-9,42-2,54-14,13-14-30,0-41-3-5-1-10-6-13-9-18-17,10-6,9-7-11-15-31-27-45-39-36-31-66-88-35-133,33-48,96,1,111-8,7-4,10-12,17-17,24-17,73,1,94,15,8,6,16,14,21,23,1,1,2,11,4,12,24,13,50,19,70,41,43,45,14,107-41,125-26,9-53,4-80,7-6,0,12,6,18,6,16,1,36-11,50,1,21,17,27,43,43,63,21,25,73,57,70,94-2,44-144,53-174,51-10,1-6,6-10,11-1,1-3-4-5-3-17,5-28,12-47,12z"/>
// </svg>
}
+74
View File
@@ -0,0 +1,74 @@
package thumbnail
import (
"math"
"testing"
"github.com/stretchr/testify/require"
)
func TestDecodePathTo(t *testing.T) {
testData := []uint8{
0x1a, 0x00, 0xb2, 0x04, 0xdc, 0x47, 0x03, 0x81, 0x73, 0x55, 0x48, 0x01, 0x46, 0x05, 0x44, 0x45,
0x4f, 0x8b, 0x52, 0x8d, 0x4e, 0x8a, 0x5d, 0x8b, 0x6e, 0x8b, 0x71, 0x81, 0x4c, 0x4d, 0x07, 0x47,
0x50, 0x02, 0x81, 0x46, 0x84, 0x4b, 0x83, 0x50, 0x80, 0x44, 0x67, 0x47, 0x01, 0x6b, 0x47, 0x08,
0x43, 0x44, 0x4f, 0x53, 0x43, 0x56, 0x8e, 0x44, 0x97, 0x94, 0x9d, 0x9c, 0x82, 0x84, 0x89, 0x45,
0x8b, 0x42, 0x88, 0x8a, 0xa6, 0xb3, 0xa8, 0xbc, 0x81, 0x8a, 0x81, 0xad, 0x82, 0xae, 0x87, 0x88,
0xa5, 0x67, 0xab, 0x6a, 0x92, 0x49, 0xaa, 0x42, 0xb6, 0x4e, 0x8d, 0x4e, 0x5e, 0x80, 0x69, 0x43,
0x45, 0x41, 0x4a, 0x46, 0x4d, 0x49, 0x52, 0x51, 0x8a, 0x46, 0x89, 0x47, 0x4b, 0x4f, 0x5f, 0x5b,
0x6d, 0x67, 0x64, 0x5f, 0x46, 0x06, 0x48, 0x08, 0x63, 0x4d, 0x03, 0xa1, 0x70, 0x89, 0x06, 0x81,
0x8b, 0x01, 0x48, 0x87, 0x44, 0x8a, 0x4c, 0x91, 0x51, 0x98, 0x51, 0x87, 0x03, 0x81, 0x89, 0x04,
0x8f, 0x88, 0x86, 0x90, 0x8e, 0x95, 0x97, 0x81, 0x81, 0x82, 0x8b, 0x84, 0x8c, 0x98, 0x8d, 0xb2,
0x93, 0x87, 0x00, 0xa9, 0xab, 0xad, 0x8e, 0x8a, 0x07, 0x69, 0x8c, 0x05, 0x5a, 0x89, 0x75, 0x84,
0x48, 0x00, 0x87, 0x46, 0x80, 0x8c, 0x86, 0x92, 0x86, 0x90, 0x81, 0xa4, 0x4b, 0xb2, 0x81, 0x95,
0x91, 0x9b, 0xab, 0xab, 0xbf, 0x95, 0x99, 0x87, 0x03, 0xb9, 0x87, 0x00, 0x89, 0x04, 0x42, 0xac,
0x4e, 0x04, 0xb5, 0x51, 0x04, 0xb3, 0x4a, 0x81, 0x46, 0x86, 0x4a, 0x8b, 0x41, 0x81, 0x43, 0x44,
0x45, 0x43, 0x51, 0x85, 0x5c, 0x8c, 0x6f, 0x8c,
}
expected := []uint8{
0x4d, 0x32, 0x36, 0x30, 0x2c, 0x35, 0x30, 0x34, 0x63, 0x2d, 0x37, 0x33, 0x2c, 0x31, 0x2d, 0x35,
0x31, 0x2d, 0x32, 0x31, 0x2d, 0x38, 0x31, 0x2d, 0x36, 0x35, 0x2d, 0x34, 0x2d, 0x35, 0x2d, 0x31,
0x35, 0x2c, 0x31, 0x31, 0x2d, 0x31, 0x38, 0x2c, 0x31, 0x33, 0x2d, 0x31, 0x34, 0x2c, 0x31, 0x30,
0x2d, 0x32, 0x39, 0x2c, 0x31, 0x31, 0x2d, 0x34, 0x36, 0x2c, 0x31, 0x31, 0x2d, 0x34, 0x39, 0x2c,
0x31, 0x2d, 0x31, 0x32, 0x2d, 0x31, 0x33, 0x37, 0x2d, 0x37, 0x2d, 0x31, 0x36, 0x32, 0x2c, 0x31,
0x2d, 0x36, 0x2c, 0x34, 0x2d, 0x31, 0x31, 0x2c, 0x33, 0x2d, 0x31, 0x36, 0x2c, 0x30, 0x2d, 0x34,
0x2d, 0x33, 0x39, 0x2d, 0x37, 0x31, 0x2d, 0x34, 0x33, 0x2d, 0x37, 0x38, 0x2d, 0x33, 0x2d, 0x34,
0x2d, 0x31, 0x35, 0x2d, 0x31, 0x39, 0x2d, 0x33, 0x2d, 0x32, 0x32, 0x2c, 0x31, 0x34, 0x2d, 0x34,
0x2c, 0x32, 0x33, 0x2c, 0x32, 0x30, 0x2c, 0x32, 0x39, 0x2c, 0x32, 0x38, 0x2c, 0x32, 0x2c, 0x34,
0x2c, 0x39, 0x2d, 0x35, 0x2c, 0x31, 0x31, 0x2d, 0x32, 0x2c, 0x38, 0x2c, 0x31, 0x30, 0x2c, 0x33,
0x38, 0x2c, 0x35, 0x31, 0x2c, 0x34, 0x30, 0x2c, 0x36, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x30, 0x2c,
0x31, 0x2c, 0x34, 0x35, 0x2c, 0x32, 0x2c, 0x34, 0x36, 0x2c, 0x37, 0x2c, 0x38, 0x2c, 0x33, 0x37,
0x2d, 0x33, 0x39, 0x2c, 0x34, 0x33, 0x2d, 0x34, 0x32, 0x2c, 0x31, 0x38, 0x2d, 0x39, 0x2c, 0x34,
0x32, 0x2d, 0x32, 0x2c, 0x35, 0x34, 0x2d, 0x31, 0x34, 0x2c, 0x31, 0x33, 0x2d, 0x31, 0x34, 0x2d,
0x33, 0x30, 0x2c, 0x30, 0x2d, 0x34, 0x31, 0x2d, 0x33, 0x2d, 0x35, 0x2d, 0x31, 0x2d, 0x31, 0x30,
0x2d, 0x36, 0x2d, 0x31, 0x33, 0x2d, 0x39, 0x2d, 0x31, 0x38, 0x2d, 0x31, 0x37, 0x2c, 0x31, 0x30,
0x2d, 0x36, 0x2c, 0x39, 0x2d, 0x37, 0x2d, 0x31, 0x31, 0x2d, 0x31, 0x35, 0x2d, 0x33, 0x31, 0x2d,
0x32, 0x37, 0x2d, 0x34, 0x35, 0x2d, 0x33, 0x39, 0x2d, 0x33, 0x36, 0x2d, 0x33, 0x31, 0x2d, 0x36,
0x36, 0x2d, 0x38, 0x38, 0x2d, 0x33, 0x35, 0x2d, 0x31, 0x33, 0x33, 0x2c, 0x33, 0x33, 0x2d, 0x34,
0x38, 0x2c, 0x39, 0x36, 0x2c, 0x31, 0x2c, 0x31, 0x31, 0x31, 0x2d, 0x38, 0x2c, 0x37, 0x2d, 0x34,
0x2c, 0x31, 0x30, 0x2d, 0x31, 0x32, 0x2c, 0x31, 0x37, 0x2d, 0x31, 0x37, 0x2c, 0x32, 0x34, 0x2d,
0x31, 0x37, 0x2c, 0x37, 0x33, 0x2c, 0x31, 0x2c, 0x39, 0x34, 0x2c, 0x31, 0x35, 0x2c, 0x38, 0x2c,
0x36, 0x2c, 0x31, 0x36, 0x2c, 0x31, 0x34, 0x2c, 0x32, 0x31, 0x2c, 0x32, 0x33, 0x2c, 0x31, 0x2c,
0x31, 0x2c, 0x32, 0x2c, 0x31, 0x31, 0x2c, 0x34, 0x2c, 0x31, 0x32, 0x2c, 0x32, 0x34, 0x2c, 0x31,
0x33, 0x2c, 0x35, 0x30, 0x2c, 0x31, 0x39, 0x2c, 0x37, 0x30, 0x2c, 0x34, 0x31, 0x2c, 0x34, 0x33,
0x2c, 0x34, 0x35, 0x2c, 0x31, 0x34, 0x2c, 0x31, 0x30, 0x37, 0x2d, 0x34, 0x31, 0x2c, 0x31, 0x32,
0x35, 0x2d, 0x32, 0x36, 0x2c, 0x39, 0x2d, 0x35, 0x33, 0x2c, 0x34, 0x2d, 0x38, 0x30, 0x2c, 0x37,
0x2d, 0x36, 0x2c, 0x30, 0x2c, 0x31, 0x32, 0x2c, 0x36, 0x2c, 0x31, 0x38, 0x2c, 0x36, 0x2c, 0x31,
0x36, 0x2c, 0x31, 0x2c, 0x33, 0x36, 0x2d, 0x31, 0x31, 0x2c, 0x35, 0x30, 0x2c, 0x31, 0x2c, 0x32,
0x31, 0x2c, 0x31, 0x37, 0x2c, 0x32, 0x37, 0x2c, 0x34, 0x33, 0x2c, 0x34, 0x33, 0x2c, 0x36, 0x33,
0x2c, 0x32, 0x31, 0x2c, 0x32, 0x35, 0x2c, 0x37, 0x33, 0x2c, 0x35, 0x37, 0x2c, 0x37, 0x30, 0x2c,
0x39, 0x34, 0x2d, 0x32, 0x2c, 0x34, 0x34, 0x2d, 0x31, 0x34, 0x34, 0x2c, 0x35, 0x33, 0x2d, 0x31,
0x37, 0x34, 0x2c, 0x35, 0x31, 0x2d, 0x31, 0x30, 0x2c, 0x31, 0x2d, 0x36, 0x2c, 0x36, 0x2d, 0x31,
0x30, 0x2c, 0x31, 0x31, 0x2d, 0x31, 0x2c, 0x31, 0x2d, 0x33, 0x2d, 0x34, 0x2d, 0x35, 0x2d, 0x33,
0x2d, 0x31, 0x37, 0x2c, 0x35, 0x2d, 0x32, 0x38, 0x2c, 0x31, 0x32, 0x2d, 0x34, 0x37, 0x2c, 0x31,
0x32, 0x7a,
}
a := require.New(t)
r := DecodePath(testData)
a.Equal(expected, r)
for i := byte(0); i < math.MaxUint8; i++ {
DecodePath([]byte{i})
}
}
+79
View File
@@ -0,0 +1,79 @@
// Package thumbnail implements expanding of stripped telegram thumbnails.
package thumbnail
import "github.com/go-faster/errors"
// Expand returns a JPG payload from stripped thumbnail bytes, like
// tg.UserProfilePhoto.StrippedThumb.
//
// See ExpandTo.
func Expand(data []byte) ([]byte, error) {
return ExpandTo(data, nil)
}
// ExpandTo appends a JPG payload to "to" byte slice, creating it from
// stripped thumbnail bytes (e.g. tg.UserProfilePhoto.StrippedThumb).
//
// See https://core.telegram.org/api/files#stripped-thumbnails for reference.
//
// Based on tdesktop implementation.
// See https://github.com/telegramdesktop/tdesktop/blob/v2.7.5/Telegram/SourceFiles/ui/image/image.cpp#L43.
func ExpandTo(data, to []byte) ([]byte, error) {
const firstChar byte = '\x01'
switch {
case len(data) < 3:
return nil, errors.Errorf("payload is too small: %d bytes", len(data))
case data[0] != firstChar:
return nil, errors.Errorf("payload must start with %#x, but got %#x", firstChar, data[0])
}
// From https://github.com/telegramdesktop/tdesktop/blob/v2.7.5/Telegram/SourceFiles/ui/image/image.cpp#L47-L82.
const (
header = "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49" +
"\x46\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00\x43\x00\x28\x1c" +
"\x1e\x23\x1e\x19\x28\x23\x21\x23\x2d\x2b\x28\x30\x3c\x64\x41\x3c\x37\x37" +
"\x3c\x7b\x58\x5d\x49\x64\x91\x80\x99\x96\x8f\x80\x8c\x8a\xa0\xb4\xe6\xc3" +
"\xa0\xaa\xda\xad\x8a\x8c\xc8\xff\xcb\xda\xee\xf5\xff\xff\xff\x9b\xc1\xff" +
"\xff\xff\xfa\xff\xe6\xfd\xff\xf8\xff\xdb\x00\x43\x01\x2b\x2d\x2d\x3c\x35" +
"\x3c\x76\x41\x41\x76\xf8\xa5\x8c\xa5\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8" +
"\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8" +
"\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8" +
"\xf8\xf8\xf8\xf8\xf8\xff\xc0\x00\x11\x08\x00\x00\x00\x00\x03\x01\x22\x00" +
"\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01" +
"\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" +
"\x09\x0a\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05" +
"\x04\x04\x00\x00\x01\x7d\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06" +
"\x13\x51\x61\x07\x22\x71\x14\x32\x81\x91\xa1\x08\x23\x42\xb1\xc1\x15\x52" +
"\xd1\xf0\x24\x33\x62\x72\x82\x09\x0a\x16\x17\x18\x19\x1a\x25\x26\x27\x28" +
"\x29\x2a\x34\x35\x36\x37\x38\x39\x3a\x43\x44\x45\x46\x47\x48\x49\x4a\x53" +
"\x54\x55\x56\x57\x58\x59\x5a\x63\x64\x65\x66\x67\x68\x69\x6a\x73\x74\x75" +
"\x76\x77\x78\x79\x7a\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96" +
"\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6" +
"\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6" +
"\xd7\xd8\xd9\xda\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf1\xf2\xf3\xf4" +
"\xf5\xf6\xf7\xf8\xf9\xfa\xff\xc4\x00\x1f\x01\x00\x03\x01\x01\x01\x01\x01" +
"\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" +
"\x09\x0a\x0b\xff\xc4\x00\xb5\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05" +
"\x04\x04\x00\x01\x02\x77\x00\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41" +
"\x51\x07\x61\x71\x13\x22\x32\x81\x08\x14\x42\x91\xa1\xb1\xc1\x09\x23\x33" +
"\x52\xf0\x15\x62\x72\xd1\x0a\x16\x24\x34\xe1\x25\xf1\x17\x18\x19\x1a\x26" +
"\x27\x28\x29\x2a\x35\x36\x37\x38\x39\x3a\x43\x44\x45\x46\x47\x48\x49\x4a" +
"\x53\x54\x55\x56\x57\x58\x59\x5a\x63\x64\x65\x66\x67\x68\x69\x6a\x73\x74" +
"\x75\x76\x77\x78\x79\x7a\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94" +
"\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4" +
"\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4" +
"\xd5\xd6\xd7\xd8\xd9\xda\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf2\xf3\xf4" +
"\xf5\xf6\xf7\xf8\xf9\xfa\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00" +
"\x3f\x00"
footer = "\xff\xd9"
)
offset := len(to)
to = append(to, header...)
to[offset+164] = data[1]
to[offset+166] = data[2]
to = append(to, data[3:]...)
to = append(to, footer...)
return to, nil
}
@@ -0,0 +1,51 @@
package thumbnail_test
import (
"bytes"
"encoding/base64"
"fmt"
"image/jpeg"
"image/png"
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/thumbnail"
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
)
func ExampleExpand() {
userPhoto := tg.UserProfilePhoto{
StrippedThumb: []uint8{
0x01, 0x28, 0x28, 0x29, 0x40, 0x1d, 0xff, 0x00, 0x2a, 0x41, 0x8e, 0xe3, 0x22, 0xac, 0x42, 0x51,
0xa0, 0x28, 0x03, 0x19, 0x1b, 0x9e, 0x07, 0x3f, 0xad, 0x69, 0x51, 0xbd, 0x91, 0xcf, 0x42, 0x29,
0xea, 0xc8, 0x9a, 0x36, 0x0a, 0x1b, 0x6e, 0x01, 0xe0, 0x73, 0xd6, 0x99, 0xdf, 0xbf, 0xe2, 0x2a,
0xdc, 0x71, 0xc8, 0xca, 0x11, 0x9d, 0x0e, 0xc3, 0xd7, 0x6f, 0x4f, 0xa5, 0x47, 0x2d, 0xb3, 0x2c,
0x84, 0x20, 0x38, 0xec, 0x71, 0xd6, 0xa6, 0x12, 0xb3, 0xd4, 0xd2, 0xac, 0x14, 0x96, 0x8b, 0x52,
0x0a, 0x2a, 0xc4, 0xb6, 0xa6, 0x38, 0x8b, 0x97, 0x04, 0x8e, 0xd8, 0xa2, 0xb6, 0x4d, 0x33, 0x95,
0xc5, 0xad, 0x1a, 0x1b, 0x04, 0xcb, 0x11, 0xf9, 0xd0, 0x11, 0xeb, 0x8e, 0x45, 0x58, 0x8e, 0x68,
0x93, 0x73, 0x96, 0x03, 0x79, 0xce, 0xd1, 0x55, 0x63, 0x50, 0x54, 0xb3, 0x64, 0xe3, 0xf0, 0x1f,
0x89, 0xa4, 0x75, 0x20, 0xee, 0xe3, 0x6f, 0x6e, 0xd9, 0xa9, 0x71, 0x4d, 0x9a, 0x46, 0x72, 0x8a,
0x2e, 0x79, 0xf2, 0x4a, 0x71, 0x02, 0x60, 0x7f, 0x79, 0xaa, 0x54, 0x46, 0x51, 0x97, 0x72, 0xcc,
0x7f, 0x2a, 0x20, 0x74, 0x78, 0xc1, 0x40, 0x00, 0xf4, 0xf4, 0xa7, 0xb3, 0x05, 0x52, 0xc7, 0xa0,
0xac, 0x9f, 0x63, 0x78, 0xae, 0xad, 0x94, 0xaf, 0xa4, 0xcb, 0x08, 0xc7, 0x41, 0xc9, 0xa2, 0xab,
0xc8, 0xe6, 0x47, 0x66, 0x3d, 0xcd, 0x15, 0xbc, 0x55, 0x91, 0xc9, 0x39, 0x73, 0x3b, 0x88, 0x09,
0x18, 0xf6, 0xe7, 0x14, 0x8c, 0xc5, 0x8e, 0x58, 0xe4, 0xd1, 0x45, 0x32, 0x6e, 0x3e, 0x19, 0x5a,
0x27, 0xdc, 0x3a, 0x77, 0x1e, 0xb5, 0x62, 0xe2, 0xe5, 0x1e, 0x1d, 0xa9, 0xd4, 0xf5, 0xe3, 0xa5,
0x14, 0x52, 0x71, 0x4d, 0xdc, 0xa5, 0x36, 0x95, 0x8a, 0x74, 0x51, 0x45, 0x32, 0x4f,
},
}
result, err := thumbnail.Expand(userPhoto.StrippedThumb)
if err != nil {
panic(err)
}
img, err := jpeg.Decode(bytes.NewReader(result))
if err != nil {
panic(err)
}
var buf bytes.Buffer
if err := png.Encode(&buf, img); err != nil {
panic(err)
}
fmt.Println("IMAGE:" + base64.StdEncoding.EncodeToString(buf.Bytes()))
}
@@ -0,0 +1,60 @@
package thumbnail
import (
"bytes"
"image/jpeg"
"testing"
"github.com/stretchr/testify/require"
"go.mau.fi/mautrix-telegram/pkg/gotd/testutil"
)
func TestExpand(t *testing.T) {
strippedImage := []byte{
0x01, 0x0e, 0x28, 0xa3, 0x9e, 0x05, 0x26, 0x78, 0xa5, 0x03, 0x8e, 0xb4, 0xd2, 0x31, 0x40, 0x06,
0x7d, 0x85, 0x19, 0xa4, 0xe2, 0x8e, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x03,
}
t.Run("Expand", func(t *testing.T) {
a := require.New(t)
to := make([]byte, 0, 1024)
testutil.ZeroAlloc(t, func() {
var err error
to, err = ExpandTo(strippedImage, to[:0])
a.NoError(err)
})
_, err := jpeg.Decode(bytes.NewReader(to))
a.NoError(err)
})
t.Run("ExpandTwice", func(t *testing.T) {
a := require.New(t)
result, err := Expand(strippedImage)
a.NoError(err)
offset := len(result)
result, err = ExpandTo(strippedImage, result)
a.NoError(err)
a.Equal(result[:offset], result[offset:])
_, err = jpeg.Decode(bytes.NewReader(result[:offset]))
a.NoError(err)
_, err = jpeg.Decode(bytes.NewReader(result[offset:]))
a.NoError(err)
})
t.Run("InvalidPrefix", func(t *testing.T) {
a := require.New(t)
_, err := ExpandTo([]byte{0x02, 0x0e, 0x28, 0xa3}, nil)
a.Error(err)
})
t.Run("InvalidLength", func(t *testing.T) {
a := require.New(t)
_, err := ExpandTo([]byte{1, 2}, nil)
a.Error(err)
})
}