Skip to content

Commit

Permalink
Merge pull request #585 from tdakkota/feat/fileid-creation-helpers
Browse files Browse the repository at this point in the history
feat(fileid): add some creation helpers
  • Loading branch information
ernado authored Nov 27, 2021
2 parents 4b1df8c + c6dc1df commit dae283d
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 103 deletions.
87 changes: 87 additions & 0 deletions fileid/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package fileid_test

import (
"context"
"os"
"testing"
"time"

"github.com/go-faster/errors"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"

"github.com/gotd/td/fileid"
"github.com/gotd/td/internal/testutil"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/downloader"
)

func runBot(ctx context.Context, token, fileID string, logger *zap.Logger) error {
bot := telegram.NewClient(telegram.TestAppID, telegram.TestAppHash, telegram.Options{
Logger: logger,
})
d := downloader.NewDownloader()

return bot.Run(ctx, func(ctx context.Context) error {
auth, err := bot.Auth().Bot(ctx, token)
if err != nil {
return errors.Wrap(err, "auth bot")
}
user, ok := auth.User.AsNotEmpty()
if !ok {
return errors.Errorf("unexpected type %T", auth.User)
}
_ = user

decoded, err := fileid.DecodeFileID(fileID)
if err != nil {
return errors.Wrap(err, "decode FileID")
}

loc, ok := decoded.AsInputFileLocation()
if !ok {
return errors.Errorf("can't map %q", fileID)
}

filename := "file.dat"
switch decoded.Type {
case fileid.Thumbnail, fileid.ProfilePhoto, fileid.Photo:
filename = "file.jpg"
case fileid.Video,
fileid.Animation,
fileid.VideoNote:
filename = "file.mp4"
case fileid.Audio:
filename = "file.mp3"
case fileid.Voice:
filename = "file.ogg"
case fileid.Sticker:
filename = "file.png"
}

if _, err := d.Download(bot.API(), loc).ToPath(ctx, filename); err != nil {
return errors.Wrap(err, "download")
}
return nil
})
}

func TestExternalE2ECheckFileID(t *testing.T) {
testutil.SkipExternal(t)
token := os.Getenv("GOTD_E2E_BOT_TOKEN")
if token == "" {
t.Skip("Set GOTD_E2E_BOT_TOKEN env to run test.")
}
fileID := os.Getenv("GOTD_E2E_FILE_ID")
if fileID == "" {
t.Skip("Set GOTD_E2E_FILE_ID env to run test.")
}
logger := zaptest.NewLogger(t)

ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

if err := runBot(ctx, token, fileID, logger.Named("bot")); err != nil {
t.Error(err)
}
}
103 changes: 0 additions & 103 deletions fileid/file_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/go-faster/errors"

"github.com/gotd/td/bin"
"github.com/gotd/td/tg"
)

// FileID represents parsed Telegram Bot API file_id.
Expand All @@ -20,108 +19,6 @@ type FileID struct {
PhotoSizeSource PhotoSizeSource
}

// AsInputWebFileLocation converts file ID to tg.InputWebFileLocationClass.
func (f FileID) AsInputWebFileLocation() (tg.InputWebFileLocationClass, bool) {
if f.URL == "" {
return nil, false
}

return &tg.InputWebFileLocation{
URL: f.URL,
AccessHash: f.AccessHash,
}, true
}

func (f FileID) asPhotoLocation() (tg.InputFileLocationClass, bool) {
switch src := f.PhotoSizeSource; src.Type {
case PhotoSizeSourceLegacy:
case PhotoSizeSourceThumbnail:
switch src.FileType {
case Photo, Thumbnail:
return &tg.InputPhotoFileLocation{
ID: f.ID,
AccessHash: f.AccessHash,
FileReference: f.FileReference,
ThumbSize: string(f.PhotoSizeSource.ThumbnailType),
}, true
}
case PhotoSizeSourceDialogPhotoSmall,
PhotoSizeSourceDialogPhotoBig:
return &tg.InputPeerPhotoFileLocation{
Big: src.Type == PhotoSizeSourceDialogPhotoBig,
Peer: src.dialogPeer(),
PhotoID: f.ID,
}, true
case PhotoSizeSourceStickerSetThumbnail:
case PhotoSizeSourceFullLegacy:
return &tg.InputPhotoLegacyFileLocation{
ID: f.ID,
AccessHash: f.AccessHash,
FileReference: f.FileReference,
VolumeID: f.PhotoSizeSource.VolumeID,
LocalID: f.PhotoSizeSource.LocalID,
Secret: f.PhotoSizeSource.Secret,
}, true
case PhotoSizeSourceDialogPhotoSmallLegacy,
PhotoSizeSourceDialogPhotoBigLegacy:
return &tg.InputPeerPhotoFileLocationLegacy{
Big: src.Type == PhotoSizeSourceDialogPhotoBigLegacy,
Peer: src.dialogPeer(),
VolumeID: f.PhotoSizeSource.VolumeID,
LocalID: f.PhotoSizeSource.LocalID,
}, true
case PhotoSizeSourceStickerSetThumbnailLegacy:
return &tg.InputStickerSetThumbLegacy{
Stickerset: f.PhotoSizeSource.stickerSet(),
VolumeID: f.PhotoSizeSource.VolumeID,
LocalID: f.PhotoSizeSource.LocalID,
}, true
case PhotoSizeSourceStickerSetThumbnailVersion:
return &tg.InputStickerSetThumb{
Stickerset: f.PhotoSizeSource.stickerSet(),
ThumbVersion: int(f.PhotoSizeSource.StickerVersion),
}, true
}

return nil, false
}

// AsInputFileLocation converts file ID to tg.InputFileLocationClass.
func (f FileID) AsInputFileLocation() (tg.InputFileLocationClass, bool) {
switch f.Type {
case Thumbnail, ProfilePhoto, Photo:
return f.asPhotoLocation()
case Encrypted:
return &tg.InputEncryptedFileLocation{
ID: f.ID,
AccessHash: f.AccessHash,
}, true
case SecureRaw,
Secure:
return &tg.InputSecureFileLocation{
ID: f.ID,
AccessHash: f.AccessHash,
}, true
case Video,
Voice,
Document,
Sticker,
Audio,
Animation,
VideoNote,
Background,
DocumentAsFile:
return &tg.InputDocumentFileLocation{
ID: f.ID,
AccessHash: f.AccessHash,
FileReference: f.FileReference,
ThumbSize: "", // ?
}, true
}

return nil, false
}

const (
webLocationFlag = 1 << 24
fileReferenceFlag = 1 << 25
Expand Down
49 changes: 49 additions & 0 deletions fileid/from.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package fileid

import "github.com/gotd/td/tg"

// FromDocument creates FileID from tg.Document.
func FromDocument(doc *tg.Document) FileID {
fileID := FileID{
Type: DocumentAsFile,
DC: doc.DCID,
ID: doc.ID,
AccessHash: doc.AccessHash,
FileReference: doc.FileReference,
}
for _, attr := range doc.Attributes {
switch attr := attr.(type) {
case *tg.DocumentAttributeAnimated:
fileID.Type = Animation
case *tg.DocumentAttributeSticker:
fileID.Type = Sticker
case *tg.DocumentAttributeVideo:
fileID.Type = Video
if attr.RoundMessage {
fileID.Type = VideoNote
}
case *tg.DocumentAttributeAudio:
fileID.Type = Audio
if attr.Voice {
fileID.Type = Voice
}
}
}
return fileID
}

// FromPhoto creates FileID from tg.Photo.
func FromPhoto(photo *tg.Photo, thumbType rune) FileID {
return FileID{
Type: Photo,
DC: photo.DCID,
ID: photo.ID,
AccessHash: photo.AccessHash,
FileReference: photo.FileReference,
PhotoSizeSource: PhotoSizeSource{
Type: PhotoSizeSourceThumbnail,
FileType: Photo,
ThumbnailType: thumbType,
},
}
}
86 changes: 86 additions & 0 deletions fileid/from_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package fileid

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/gotd/td/tg"
)

func TestFromDocument(t *testing.T) {
doc := func(attrs ...tg.DocumentAttributeClass) *tg.Document {
return &tg.Document{
ID: 1,
AccessHash: 2,
FileReference: []byte{3},
DCID: 4,
Attributes: attrs,
}
}
fileID := func(typ Type) FileID {
return FileID{
Type: typ,
ID: 1,
AccessHash: 2,
FileReference: []byte{3},
DC: 4,
}
}

tests := []struct {
name string
doc *tg.Document
want FileID
}{
{"File", doc(), fileID(DocumentAsFile)},
{"Animation", doc(&tg.DocumentAttributeAnimated{}), fileID(Animation)},
{"Sticker", doc(&tg.DocumentAttributeSticker{}), fileID(Sticker)},
{"Video", doc(&tg.DocumentAttributeVideo{}), fileID(Video)},
{"VideoNote", doc(&tg.DocumentAttributeVideo{RoundMessage: true}), fileID(VideoNote)},
{"Audio", doc(&tg.DocumentAttributeAudio{}), fileID(Audio)},
{"Voice", doc(&tg.DocumentAttributeAudio{Voice: true}), fileID(Voice)},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, FromDocument(tt.doc))
})
}
}

func TestFromPhoto(t *testing.T) {
tests := []struct {
name string
photo *tg.Photo
size rune
want FileID
}{
{
"Photo",
&tg.Photo{
ID: 1,
AccessHash: 2,
FileReference: []byte{3},
DCID: 4,
},
'x',
FileID{
Type: Photo,
ID: 1,
AccessHash: 2,
FileReference: []byte{3},
DC: 4,
PhotoSizeSource: PhotoSizeSource{
Type: PhotoSizeSourceThumbnail,
FileType: Photo,
ThumbnailType: 'x',
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, FromPhoto(tt.photo, tt.size))
})
}
}
Loading

0 comments on commit dae283d

Please sign in to comment.