package sniper import ( "context" "math/rand" "strconv" "time" ) func int32String(value int32) string { return strconv.FormatInt(int64(value), 10) } func int64String(value int64) string { return strconv.FormatInt(value, 10) } func sleepContext(ctx context.Context, d time.Duration) error { timer := time.NewTimer(d) defer timer.Stop() select { case <-timer.C: return nil case <-ctx.Done(): return ctx.Err() } } func maxDuration(a, b time.Duration) time.Duration { if a > b { return a } return b } func maxInt(a, b int) int { if a > b { return a } return b } // jitterDuration 在基准退避上叠加 0-25% 的随机抖动。 // // 多个账号同时失败时,固定退避会让它们在同一个时刻整批重试,形成周期性尖峰, // 更容易撞上限频(参考 dygou_go 的 jitterFraction)。这里只往长了抖,不缩短, // 保证配置值始终是退避下限。 func jitterDuration(base time.Duration) time.Duration { if base <= 0 { return base } span := int64(base) / 4 if span <= 0 { return base } return base + time.Duration(rand.Int63n(span+1)) }