Skip to content

Instantly share code, notes, and snippets.

@ernado
Last active April 8, 2024 11:31
Show Gist options
  • Save ernado/3784de00cf781f6f00025742a9b51e1b to your computer and use it in GitHub Desktop.
Save ernado/3784de00cf781f6f00025742a9b51e1b to your computer and use it in GitHub Desktop.
gotd upload example
package main
import (
"context"
"os"
"path/filepath"
"time"
"github.com/dustin/go-humanize"
"github.com/go-faster/errors"
"github.com/gotd/td/telegram/message"
"github.com/gotd/td/telegram/uploader"
"github.com/gotd/td/tg"
"go.uber.org/zap"
)
type progressFunc func(ctx context.Context, state uploader.ProgressState) error
func (f progressFunc) Chunk(ctx context.Context, state uploader.ProgressState) error {
return f(ctx, state)
}
func Upload(ctx context.Context, lg *zap.Logger, target tg.InputPeerClass, api *tg.Client, file string) error {
lg = lg.With(zap.String("file", file))
stat, err := os.Stat(file)
if err != nil {
return errors.Wrap(err, "stat")
}
const (
kb int = 1024
mb = kb * 1024
gb = mb * 1024
)
partSize := 128 * 1024
size := int(stat.Size())
if size > 100*mb {
partSize = uploader.MaximumPartSize
}
if size > 4*gb {
return errors.Wrapf(err, "%s: file too big", file)
}
var lastNotify time.Time
start := time.Now()
notifyRate := time.Second * 5
onProgress := progressFunc(func(ctx context.Context, state uploader.ProgressState) error {
now := time.Now()
if now.Sub(lastNotify) < notifyRate {
return nil
}
lastNotify = now
progress := int(100 * (float64(state.Uploaded) / float64(state.Total)))
perSecond := float64(state.Uploaded) / now.Sub(start).Seconds()
lg.Info("Progress",
zap.Int64("total", state.Total),
zap.Int64("uploaded", state.Uploaded),
zap.Int("percent", progress),
zap.String("speed", humanize.Bytes(uint64(perSecond))+"/s"),
)
return nil
})
inputFile, err := uploader.NewUploader(api).
WithProgress(onProgress).
WithPartSize(partSize).
WithThreads(1).
FromPath(ctx, file)
if err != nil {
return errors.Wrap(err, "upload")
}
lg.Info("Uploaded",
zap.String("file", filepath.Base(file)),
)
if _, err := message.NewSender(api).
To(target).
File(ctx, inputFile); err != nil {
return errors.Wrap(err, "send")
}
lg.Info("Done")
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment