From 610f586d45abd839485ee459fd765f469ba424fe Mon Sep 17 00:00:00 2001 From: krau <71133316+krau@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:28:07 +0800 Subject: [PATCH] refactor: share progress throttling helpers Move size-tiered and count-based throttling into progressutil. Localize hardcoded Chinese progress strings. Drop five duplicated implementations and dead local copies. --- common/utils/progressutil/progress.go | 53 +++++++++++++++++++++++++++ core/tasks/batchtfile/utils.go | 32 ---------------- core/tasks/directlinks/progress.go | 8 +++- core/tasks/directlinks/util.go | 31 ---------------- core/tasks/parsed/progress.go | 44 +++++----------------- core/tasks/telegraph/progress.go | 3 +- core/tasks/telegraph/utils.go | 13 ------- core/tasks/tfile/progress.go | 5 ++- core/tasks/tfile/util.go | 32 ---------------- core/tasks/transfer/progress.go | 11 +----- 10 files changed, 76 insertions(+), 156 deletions(-) create mode 100644 common/utils/progressutil/progress.go delete mode 100644 core/tasks/batchtfile/utils.go delete mode 100644 core/tasks/telegraph/utils.go delete mode 100644 core/tasks/tfile/util.go diff --git a/common/utils/progressutil/progress.go b/common/utils/progressutil/progress.go new file mode 100644 index 0000000..15df39b --- /dev/null +++ b/common/utils/progressutil/progress.go @@ -0,0 +1,53 @@ +// Package progressutil provides shared progress-update throttling used by +// task progress trackers. All task packages must use these helpers instead +// of re-implementing throttle logic. +package progressutil + +// updatesLevels sizes files by their total size and picks how often the +// progress percent may be reported: smaller files report less often. +var updatesLevels = []struct { + size int64 // file size threshold + stepPercent int // minimum percent step between updates +}{ + {10 << 20, 100}, + {50 << 20, 20}, + {200 << 20, 10}, + {500 << 20, 5}, +} + +// ShouldUpdate reports whether a byte-based progress update should be shown, +// throttled by a minimum percent step that shrinks as the total grows. +func ShouldUpdate(total, downloaded int64, lastUpdatePercent int) bool { + if total <= 0 || downloaded <= 0 { + return false + } + + percent := int((downloaded * 100) / total) + if percent <= lastUpdatePercent { + return false + } + + step := updatesLevels[len(updatesLevels)-1].stepPercent + for _, lvl := range updatesLevels { + if total < lvl.size { + step = lvl.stepPercent + break + } + } + + return percent >= lastUpdatePercent+step +} + +// ShouldUpdateCount reports whether a count-based progress update (e.g. files +// downloaded so far) should be shown: every 10 units, or when finished. +func ShouldUpdateCount(downloaded, total int64) bool { + if total <= 0 || downloaded <= 0 { + return false + } + + const step = int64(10) + if downloaded < step { + return downloaded == total + } + return downloaded%step == 0 || downloaded == total +} diff --git a/core/tasks/batchtfile/utils.go b/core/tasks/batchtfile/utils.go deleted file mode 100644 index b8c39cd..0000000 --- a/core/tasks/batchtfile/utils.go +++ /dev/null @@ -1,32 +0,0 @@ -package batchtfile - -var progressUpdatesLevels = []struct { - size int64 // 文件大小阈值 - stepPercent int // 每多少 % 更新一次 -}{ - {10 << 20, 100}, - {50 << 20, 20}, - {200 << 20, 10}, - {500 << 20, 5}, -} - -func shouldUpdateProgress(total, downloaded int64, lastUpdatePercent int) bool { - if total <= 0 || downloaded <= 0 { - return false - } - - percent := int((downloaded * 100) / total) - if percent <= lastUpdatePercent { - return false - } - - step := progressUpdatesLevels[len(progressUpdatesLevels)-1].stepPercent - for _, lvl := range progressUpdatesLevels { - if total < lvl.size { - step = lvl.stepPercent - break - } - } - - return percent >= lastUpdatePercent+step -} diff --git a/core/tasks/directlinks/progress.go b/core/tasks/directlinks/progress.go index 223a50c..bd72ac2 100644 --- a/core/tasks/directlinks/progress.go +++ b/core/tasks/directlinks/progress.go @@ -15,6 +15,7 @@ import ( "github.com/krau/SaveAny-Bot/common/i18n" "github.com/krau/SaveAny-Bot/common/i18n/i18nk" "github.com/krau/SaveAny-Bot/common/utils/dlutil" + "github.com/krau/SaveAny-Bot/common/utils/progressutil" "github.com/krau/SaveAny-Bot/common/utils/tgutil" ) @@ -102,7 +103,7 @@ func (p *Progress) OnDone(ctx context.Context, info TaskInfo, err error) { // OnProgress implements ProgressTracker. func (p *Progress) OnProgress(ctx context.Context, info TaskInfo) { - if !shouldUpdateProgress(info.TotalBytes(), info.DownloadedBytes(), int(p.lastUpdatePercent.Load())) { + if !progressutil.ShouldUpdate(info.TotalBytes(), info.DownloadedBytes(), int(p.lastUpdatePercent.Load())) { return } percent := int((info.DownloadedBytes() * 100) / info.TotalBytes()) @@ -115,7 +116,10 @@ func (p *Progress) OnProgress(ctx context.Context, info TaskInfo) { var entities []tg.MessageEntityClass if err := styling.Perform(&entityBuilder, styling.Plain(i18n.T(i18nk.BotMsgProgressDownloadingPrefix, nil)), - styling.Code(fmt.Sprintf("%.2f MB (%d个文件)", float64(info.TotalBytes())/(1024*1024), info.TotalFiles())), + styling.Code(i18n.T(i18nk.BotMsgProgressSizeWithFiles, map[string]any{ + "Size": fmt.Sprintf("%.2f MB", float64(info.TotalBytes())/(1024*1024)), + "Count": info.TotalFiles(), + })), styling.Plain(i18n.T(i18nk.BotMsgProgressProcessingListPrefix, nil)), func() styling.StyledTextOption { var lines []string diff --git a/core/tasks/directlinks/util.go b/core/tasks/directlinks/util.go index 57d19c2..5373b9f 100644 --- a/core/tasks/directlinks/util.go +++ b/core/tasks/directlinks/util.go @@ -207,34 +207,3 @@ func parseFilenameFallback(cd string) string { return decodeFilenameParam(value) } - -var progressUpdatesLevels = []struct { - size int64 // 文件大小阈值 - stepPercent int // 每多少 % 更新一次 -}{ - {10 << 20, 100}, - {50 << 20, 50}, - {200 << 20, 20}, - {500 << 20, 10}, -} - -func shouldUpdateProgress(total, downloaded int64, lastUpdatePercent int) bool { - if total <= 0 || downloaded <= 0 { - return false - } - - percent := int((downloaded * 100) / total) - if percent <= lastUpdatePercent { - return false - } - - step := progressUpdatesLevels[len(progressUpdatesLevels)-1].stepPercent - for _, lvl := range progressUpdatesLevels { - if total < lvl.size { - step = lvl.stepPercent - break - } - } - - return percent >= lastUpdatePercent+step -} diff --git a/core/tasks/parsed/progress.go b/core/tasks/parsed/progress.go index 0cac6c4..6d0aa66 100644 --- a/core/tasks/parsed/progress.go +++ b/core/tasks/parsed/progress.go @@ -15,40 +15,10 @@ import ( "github.com/krau/SaveAny-Bot/common/i18n" "github.com/krau/SaveAny-Bot/common/i18n/i18nk" "github.com/krau/SaveAny-Bot/common/utils/dlutil" + "github.com/krau/SaveAny-Bot/common/utils/progressutil" "github.com/krau/SaveAny-Bot/common/utils/tgutil" ) -var progressUpdatesLevels = []struct { - size int64 // 文件大小阈值 - stepPercent int // 每多少 % 更新一次 -}{ - {10 << 20, 100}, - {50 << 20, 50}, - {200 << 20, 20}, - {500 << 20, 10}, -} - -func shouldUpdateProgress(total, downloaded int64, lastUpdatePercent int) bool { - if total <= 0 || downloaded <= 0 { - return false - } - - percent := int((downloaded * 100) / total) - if percent <= lastUpdatePercent { - return false - } - - step := progressUpdatesLevels[len(progressUpdatesLevels)-1].stepPercent - for _, lvl := range progressUpdatesLevels { - if total < lvl.size { - step = lvl.stepPercent - break - } - } - - return percent >= lastUpdatePercent+step -} - type ProgressTracker interface { OnStart(ctx context.Context, info TaskInfo) OnProgress(ctx context.Context, info TaskInfo) @@ -73,7 +43,10 @@ func (p *Progress) OnStart(ctx context.Context, info TaskInfo) { styling.Plain(i18n.T(i18nk.BotMsgProgressParsedStartPrefix, map[string]any{ "Site": info.Site(), })), - styling.Code(fmt.Sprintf("%.2f MB (%d个资源)", float64(info.TotalBytes())/(1024*1024), info.TotalResources())), + styling.Code(i18n.T(i18nk.BotMsgProgressSizeWithResources, map[string]any{ + "Size": fmt.Sprintf("%.2f MB", float64(info.TotalBytes())/(1024*1024)), + "Count": info.TotalResources(), + })), ); err != nil { log.FromContext(ctx).Errorf("Failed to build entities: %s", err) return @@ -101,7 +74,7 @@ func (p *Progress) OnStart(ctx context.Context, info TaskInfo) { } func (p *Progress) OnProgress(ctx context.Context, info TaskInfo) { - if !shouldUpdateProgress(info.TotalBytes(), info.DownloadedBytes(), int(p.lastUpdatePercent.Load())) { + if !progressutil.ShouldUpdate(info.TotalBytes(), info.DownloadedBytes(), int(p.lastUpdatePercent.Load())) { return } percent := int((info.DownloadedBytes() * 100) / info.TotalBytes()) @@ -114,7 +87,10 @@ func (p *Progress) OnProgress(ctx context.Context, info TaskInfo) { var entities []tg.MessageEntityClass if err := styling.Perform(&entityBuilder, styling.Plain(i18n.T(i18nk.BotMsgProgressDownloadingPrefix, nil)), - styling.Code(fmt.Sprintf("%.2f MB (%d个文件)", float64(info.TotalBytes())/(1024*1024), info.TotalResources())), + styling.Code(i18n.T(i18nk.BotMsgProgressSizeWithFiles, map[string]any{ + "Size": fmt.Sprintf("%.2f MB", float64(info.TotalBytes())/(1024*1024)), + "Count": info.TotalResources(), + })), styling.Plain(i18n.T(i18nk.BotMsgProgressProcessingListPrefix, nil)), func() styling.StyledTextOption { var lines []string diff --git a/core/tasks/telegraph/progress.go b/core/tasks/telegraph/progress.go index cc58027..bac2d50 100644 --- a/core/tasks/telegraph/progress.go +++ b/core/tasks/telegraph/progress.go @@ -11,6 +11,7 @@ import ( "github.com/gotd/td/tg" "github.com/krau/SaveAny-Bot/common/i18n" "github.com/krau/SaveAny-Bot/common/i18n/i18nk" + "github.com/krau/SaveAny-Bot/common/utils/progressutil" "github.com/krau/SaveAny-Bot/common/utils/tgutil" ) @@ -60,7 +61,7 @@ func (p *Progress) OnStart(ctx context.Context, info TaskInfo) { } func (p *Progress) OnProgress(ctx context.Context, info TaskInfo) { - if !shouldUpdateProgress(info.Downloaded(), int64(info.TotalPics())) { + if !progressutil.ShouldUpdateCount(info.Downloaded(), int64(info.TotalPics())) { return } log.FromContext(ctx).Debugf("Progress update: %s, %d/%d", info.TaskID(), info.Downloaded(), info.TotalPics()) diff --git a/core/tasks/telegraph/utils.go b/core/tasks/telegraph/utils.go deleted file mode 100644 index ce109eb..0000000 --- a/core/tasks/telegraph/utils.go +++ /dev/null @@ -1,13 +0,0 @@ -package telegraph - -func shouldUpdateProgress(downloaded int64, total int64) bool { - if total <= 0 || downloaded <= 0 { - return false - } - - step := int64(10) - if downloaded < step { - return downloaded == total - } - return downloaded%step == 0 || downloaded == total -} diff --git a/core/tasks/tfile/progress.go b/core/tasks/tfile/progress.go index fb6be21..c0bbe91 100644 --- a/core/tasks/tfile/progress.go +++ b/core/tasks/tfile/progress.go @@ -14,6 +14,7 @@ import ( "github.com/krau/SaveAny-Bot/common/i18n" "github.com/krau/SaveAny-Bot/common/i18n/i18nk" "github.com/krau/SaveAny-Bot/common/utils/dlutil" + "github.com/krau/SaveAny-Bot/common/utils/progressutil" "github.com/krau/SaveAny-Bot/common/utils/tgutil" ) @@ -111,7 +112,7 @@ func (p *Progress) OnProgress(ctx context.Context, info TaskInfo, downloaded, to func shouldUpdateSingleDownloadProgress(total, downloaded int64, lastPercent int, elapsed time.Duration) bool { if total > 0 { - return shouldUpdateProgress(total, downloaded, lastPercent) + return progressutil.ShouldUpdate(total, downloaded, lastPercent) } return downloaded > 0 && elapsed >= uploadProgressMaxInterval } @@ -183,7 +184,7 @@ func shouldUpdateUploadProgress(total, uploaded int64, lastPercent int, elapsed if percent == lastPercent { return elapsed >= uploadProgressMaxInterval } - return shouldUpdateProgress(total, uploaded, lastPercent) || elapsed >= uploadProgressMaxInterval + return progressutil.ShouldUpdate(total, uploaded, lastPercent) || elapsed >= uploadProgressMaxInterval } func singleUploadPhase(attempt int) singleProgressPhase { diff --git a/core/tasks/tfile/util.go b/core/tasks/tfile/util.go deleted file mode 100644 index 81862d9..0000000 --- a/core/tasks/tfile/util.go +++ /dev/null @@ -1,32 +0,0 @@ -package tfile - -var progressUpdatesLevels = []struct { - size int64 // 文件大小阈值 - stepPercent int // 每多少 % 更新一次 -}{ - {10 << 20, 100}, - {50 << 20, 20}, - {200 << 20, 10}, - {500 << 20, 5}, -} - -func shouldUpdateProgress(total, downloaded int64, lastUpdatePercent int) bool { - if total <= 0 || downloaded <= 0 { - return false - } - - percent := int((downloaded * 100) / total) - if percent <= lastUpdatePercent { - return false - } - - step := progressUpdatesLevels[len(progressUpdatesLevels)-1].stepPercent - for _, lvl := range progressUpdatesLevels { - if total < lvl.size { - step = lvl.stepPercent - break - } - } - - return percent >= lastUpdatePercent+step -} diff --git a/core/tasks/transfer/progress.go b/core/tasks/transfer/progress.go index 2852524..bd538b3 100644 --- a/core/tasks/transfer/progress.go +++ b/core/tasks/transfer/progress.go @@ -14,6 +14,7 @@ import ( "github.com/krau/SaveAny-Bot/common/i18n" "github.com/krau/SaveAny-Bot/common/i18n/i18nk" "github.com/krau/SaveAny-Bot/common/utils/dlutil" + "github.com/krau/SaveAny-Bot/common/utils/progressutil" "github.com/krau/SaveAny-Bot/common/utils/tgutil" ) @@ -83,7 +84,7 @@ func (p *Progress) OnStart(ctx context.Context, info TaskInfo) { } func (p *Progress) OnProgress(ctx context.Context, info TaskInfo) { - if !shouldUpdateProgress(info.TotalSize(), info.Uploaded(), int(p.lastUpdatePercent.Load())) { + if !progressutil.ShouldUpdate(info.TotalSize(), info.Uploaded(), int(p.lastUpdatePercent.Load())) { return } percent := int((info.Uploaded() * 100) / info.TotalSize()) @@ -221,14 +222,6 @@ func (p *Progress) OnDone(ctx context.Context, info TaskInfo, err error) { } } -func shouldUpdateProgress(total, current int64, lastPercent int) bool { - if total == 0 { - return false - } - currentPercent := int((current * 100) / total) - return currentPercent > lastPercent && currentPercent%5 == 0 -} - func formatDuration(d time.Duration) string { d = d.Round(time.Second) h := d / time.Hour