uploader: FromReader always uploads as inputFileBig, and Telegram then refuses to classify the media

Open Beginner friendly
#1,845 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Documentation
Clarity
Clearly specified
Activity status
Quiet
Tech stack
go
Domain
documentation

Research direction

Start with telegram/uploader/helpers.go, telegram/uploader/uploader.go, telegram/message/file_promise.go, and the NewUpload definition. Document that unknown length and total=-1 use inputFileBig without an MD5 checksum, explain the media-classification consequence, and recommend FromFile when the size is known. Confirm the note covers uploader.FromReader, message.FromReader, and NewUpload.

Written by the indexing model from the issue text.

Description

Summary

FromReader uploads as inputFileBig regardless of size, because it cannot know the length. That is a reasonable implementation, but it has a consequence nothing documents: Telegram stops classifying the media. A soundless mp4 sent with documentAttributeAnimated arrives as an ordinary video, and a round_message video note arrives as a plain video — with byte-identical content and identical attributes to an upload that works.

The attributes are not the problem, so the symptom points at entirely the wrong layer. It cost me most of a day.

Why it happens

FromReader passes -1 as the total size:

// telegram/uploader/helpers.go:65
func (u *Uploader) FromReader(ctx context.Context, name string, f io.Reader) (tg.InputFileClass, error) {
	return u.Upload(ctx, NewUpload(name, f, -1))
}

which Upload turns into a big-file upload:

// telegram/uploader/uploader.go:114
if upload.totalBytes == -1 {
	upload.big = true
	upload.totalParts = -1
}

uploadBig returns inputFileBig, which has no md5_checksum field, while uploadSmall sets one (uploader.go:136). So a 291 KB file goes out the way a 2 GB one does, and unlike any official client.

message.FromReader (telegram/message/file_promise.go:98) inherits this, which is where most callers meet it.

Reproduction

Same bytes, same attributes, same account, one send each way:

upload attributes sent arrives as
message.FromReader(name, r) filename, documentAttributeAnimated, documentAttributeVideo video
message.FromFile(f) — identical bytes identical gif

Same for a video note: round_message is honoured through FromFile and dropped through FromReader. The file used was downloaded from a message Telegram itself serves as an animation, so the encoding is known-good.

Verified against gotd v0.161.0.

Suggested fix

Documentation, primarily. Something like:

// FromReader uploads file from given io.Reader.
//
// The length is unknown, so the file is uploaded as inputFileBig whatever its
// size, without an MD5 checksum. Telegram does not classify the media of a
// big-file upload: a soundless mp4 will not become an animation and a round
// video will not stay round, however the document attributes are set. Prefer
// FromFile when the size is known.
func FromReader(name string, r io.Reader) UploadOption

The same note is worth having on uploader.FromReader and on NewUpload, whose total parameter is where the -1 convention actually lives — it is currently undocumented that -1 means "stream as big file".

A FromReaderSize(name string, r io.Reader, size int64) helper would remove the need for callers to write a uploader.File adapter just to report a size they already know. Happy to send a PR for either if useful.

Dominant language
Go
Stars
2.3k
Forks
210
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from gotd/td

All issues in gotd/td

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.