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
+104
View File
@@ -0,0 +1,104 @@
package downloader
import (
"bytes"
"context"
"sort"
"sync"
"github.com/go-faster/errors"
"go.mau.fi/mautrix-telegram/pkg/gotd/crypto"
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
"go.mau.fi/mautrix-telegram/pkg/gotd/tgerr"
)
// ErrHashMismatch means that download hash verification was failed.
var ErrHashMismatch = errors.New("file hash mismatch")
type verifier struct {
client schema
hashes []tg.FileHash
offset int64
mux sync.Mutex
}
func newVerifier(client schema, hashes ...tg.FileHash) *verifier {
r := make([]tg.FileHash, len(hashes))
copy(r, hashes)
sort.SliceStable(r, func(i, j int) bool {
return r[i].Offset < r[j].Offset
})
return &verifier{client: client, hashes: r}
}
func (v *verifier) pop() (tg.FileHash, bool) {
if len(v.hashes) < 1 {
return tg.FileHash{}, false
}
// Pop and move.
hash := v.hashes[0]
copy(v.hashes, v.hashes[1:])
v.hashes[len(v.hashes)-1] = tg.FileHash{}
v.hashes = v.hashes[:len(v.hashes)-1]
return hash, true
}
func (v *verifier) update(hashes ...tg.FileHash) (tg.FileHash, bool) {
// If result is empty and queue is empty, so we can't return next hash.
if len(hashes) < 1 {
return tg.FileHash{}, false
}
// Sort hashes by offset.
// Usually Telegram server returns sorted parts, but...
// you never known what can they do.
sort.SliceStable(hashes, func(i, j int) bool {
return hashes[i].Offset < hashes[j].Offset
})
last := hashes[len(hashes)-1]
// Check if we have reached the end.
// If current state offset is equal the last offset + limit (right border)
// then we got all hashes.
if last.Offset == v.offset-int64(last.Limit) {
return tg.FileHash{}, false
}
// Otherwise, we update current offset and add hashes to the end of queue.
v.offset = last.Offset + int64(last.Limit)
v.hashes = append(v.hashes, hashes...)
return v.pop()
}
func (v *verifier) next(ctx context.Context) (tg.FileHash, bool, error) {
v.mux.Lock()
defer v.mux.Unlock()
hash, ok := v.pop()
if ok {
return hash, ok, nil
}
for {
hashes, err := v.client.Hashes(ctx, v.offset)
if flood, err := tgerr.FloodWait(ctx, err); err != nil {
if flood || tgerr.Is(err, tg.ErrTimeout) {
continue
}
return tg.FileHash{}, false, errors.Wrap(err, "get hashes")
}
hash, ok = v.update(hashes...)
return hash, ok, nil
}
}
func (v *verifier) verify(hash tg.FileHash, data []byte) bool {
return bytes.Equal(crypto.SHA256(data), hash.Hash)
}