Files
mautrix-telegram/pkg/gotd/fileid/file_id.go
T
2025-06-27 20:03:37 -07:00

132 lines
2.3 KiB
Go

package fileid
import (
"io"
"github.com/go-faster/errors"
"go.mau.fi/mautrix-telegram/pkg/gotd/bin"
)
// FileID represents parsed Telegram Bot API file_id.
type FileID struct {
Type Type
DC int
ID int64
AccessHash int64
FileReference []byte
URL string
PhotoSizeSource PhotoSizeSource
}
const (
webLocationFlag = 1 << 24
fileReferenceFlag = 1 << 25
)
func (f *FileID) decodeLatestFileID(b *bin.Buffer) error {
if len(b.Buf) < 1 {
return io.ErrUnexpectedEOF
}
var subVersion = b.Buf[len(b.Buf)-1]
typeID, err := b.Uint32()
if err != nil {
return errors.Wrap(err, "read type_id")
}
hasWebLocation := typeID&webLocationFlag != 0
hasReference := typeID&fileReferenceFlag != 0
typeID &^= webLocationFlag
typeID &^= fileReferenceFlag
if typeID >= uint32(lastType) {
return errors.Errorf("unknown type %d", typeID)
}
f.Type = Type(typeID)
{
dcID, err := b.Uint32()
if err != nil {
return errors.Wrap(err, "read dc_id")
}
f.DC = int(dcID)
}
if hasReference {
reference, err := b.Bytes()
if err != nil {
return errors.Wrap(err, "read file_reference")
}
f.FileReference = reference
}
if hasWebLocation {
url, err := b.String()
if err != nil {
return errors.Wrap(err, "read url")
}
f.URL = url
return nil
}
{
id, err := b.Long()
if err != nil {
return errors.Wrap(err, "read id")
}
f.ID = id
}
{
accessHash, err := b.Long()
if err != nil {
return errors.Wrap(err, "read access_hash")
}
f.AccessHash = accessHash
}
switch Type(typeID) {
case Thumbnail, Photo, ProfilePhoto:
default:
return nil
}
if err := f.PhotoSizeSource.decode(b, subVersion); err != nil {
return errors.Wrap(err, "decode photo_size")
}
return nil
}
func (f *FileID) encodeLatestFileID(b *bin.Buffer) {
hasWebLocation := f.URL != ""
hasReference := len(f.FileReference) != 0
{
typeID := f.Type
if hasWebLocation {
typeID |= webLocationFlag
}
if hasReference {
typeID |= fileReferenceFlag
}
b.PutUint32(uint32(typeID))
}
b.PutUint32(uint32(f.DC))
if hasReference {
b.PutBytes(f.FileReference)
}
if hasWebLocation {
b.PutString(f.URL)
return
}
b.PutLong(f.ID)
b.PutLong(f.AccessHash)
switch f.Type {
case Thumbnail, Photo, ProfilePhoto:
f.PhotoSizeSource.encode(b)
}
b.Buf = append(b.Buf, latestSubVersion)
}