From d81ab0071899f2349d8e4c73017b90d05a4444d8 Mon Sep 17 00:00:00 2001 From: Andre-cc <15630108053@163.com> Date: Tue, 23 Sep 2025 22:33:35 +0800 Subject: [PATCH] feat(up,uploader): add --video/--audio flags and forced media type handling --- app/up/up.go | 13 +++++--- cmd/up.go | 5 +++ core/uploader/uploader.go | 65 +++++++++++++++++++++++++++------------ 3 files changed, 59 insertions(+), 24 deletions(-) diff --git a/app/up/up.go b/app/up/up.go index bea93ffa7..bfde0a80c 100644 --- a/app/up/up.go +++ b/app/up/up.go @@ -27,6 +27,9 @@ type Options struct { Excludes []string Remove bool Photo bool + // Force type overrides auto-detection + Video bool + Audio bool } func Run(ctx context.Context, c *telegram.Client, kvd storage.Storage, opts Options) (rerr error) { @@ -54,10 +57,12 @@ func Run(ctx context.Context, c *telegram.Client, kvd storage.Storage, opts Opti prog.EnablePS(ctx, upProgress) options := uploader.Options{ - Client: pool.Default(ctx), - Threads: viper.GetInt(consts.FlagThreads), - Iter: newIter(files, to, opts.Photo, opts.Remove, viper.GetDuration(consts.FlagDelay)), - Progress: newProgress(upProgress), + Client: pool.Default(ctx), + Threads: viper.GetInt(consts.FlagThreads), + Iter: newIter(files, to, opts.Photo, opts.Remove, viper.GetDuration(consts.FlagDelay)), + Progress: newProgress(upProgress), + ForceVideo: opts.Video, + ForceAudio: opts.Audio, } up := uploader.New(options) diff --git a/cmd/up.go b/cmd/up.go index a3994e77c..cc934bfef 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -36,8 +36,13 @@ func NewUpload() *cobra.Command { cmd.Flags().BoolVar(&opts.Remove, "rm", false, "remove the uploaded files after uploading") cmd.Flags().BoolVar(&opts.Photo, "photo", false, "upload the image as a photo instead of a file") + // force type flags (mutually exclusive) + cmd.Flags().BoolVar(&opts.Video, "video", false, "force upload as video (override auto-detection)") + cmd.Flags().BoolVar(&opts.Audio, "audio", false, "force upload as audio (override auto-detection)") + // completion and validation _ = cmd.MarkFlagRequired(path) + cmd.MarkFlagsMutuallyExclusive("video", "audio") return cmd } diff --git a/core/uploader/uploader.go b/core/uploader/uploader.go index 11d5da823..50e187de7 100644 --- a/core/uploader/uploader.go +++ b/core/uploader/uploader.go @@ -29,6 +29,9 @@ type Options struct { Threads int Iter Iter Progress Progress + // Force type overrides auto-detection + ForceVideo bool + ForceAudio bool } func New(o Options) *Uploader { @@ -112,28 +115,50 @@ func (u *Uploader) upload(ctx context.Context, elem Elem) error { var media message.MediaOption = doc - switch { - case mediautil.IsImage(mime.String()) && elem.AsPhoto(): - // webp should be uploaded as document - if mime.String() == "image/webp" { - break - } - // upload as photo - media = message.UploadedPhoto(f, caption...) - case mediautil.IsVideo(mime.String()): - // reset reader - if _, err = elem.File().Seek(0, io.SeekStart); err != nil { - return errors.Wrap(err, "seek file") - } - if dur, w, h, err := mediautil.GetMP4Info(elem.File()); err == nil { - // #132. There may be some errors, but we can still upload the file - media = doc.Video(). - Duration(time.Duration(dur)*time.Second). - Resolution(w, h). - SupportsStreaming() + // Forced overriding by CLI flags + if u.opts.ForceVideo { + if _, err = elem.File().Seek(0, io.SeekStart); err == nil { + if dur, w, h, err := mediautil.GetMP4Info(elem.File()); err == nil { + // override MIME to video to avoid audio/misclassification + doc = doc.MIME("video/mp4") + media = doc.Video(). + Duration(time.Duration(dur)*time.Second). + Resolution(w, h). + SupportsStreaming() + } else { + doc = doc.MIME("video/mp4") + media = doc.Video().SupportsStreaming() + } + } else { + doc = doc.MIME("video/mp4") + media = doc.Video().SupportsStreaming() } - case mediautil.IsAudio(mime.String()): + } else if u.opts.ForceAudio { media = doc.Audio().Title(fsutil.GetNameWithoutExt(elem.File().Name())) + } else { + switch { + case mediautil.IsImage(mime.String()) && elem.AsPhoto(): + // webp should be uploaded as document + if mime.String() == "image/webp" { + break + } + // upload as photo + media = message.UploadedPhoto(f, caption...) + case mediautil.IsVideo(mime.String()): + // reset reader + if _, err = elem.File().Seek(0, io.SeekStart); err != nil { + return errors.Wrap(err, "seek file") + } + if dur, w, h, err := mediautil.GetMP4Info(elem.File()); err == nil { + // #132. There may be some errors, but we can still upload the file + media = doc.Video(). + Duration(time.Duration(dur)*time.Second). + Resolution(w, h). + SupportsStreaming() + } + case mediautil.IsAudio(mime.String()): + media = doc.Audio().Title(fsutil.GetNameWithoutExt(elem.File().Name())) + } } _, err = message.NewSender(u.opts.Client).