@@ -179,38 +179,20 @@ func (m *Manager) GetAllMobile() []UserAgent {
179179 return agents
180180}
181181
182- // GetRandomDesktop returns a random desktop UserAgent using crypto/rand
182+ // GetRandomDesktop returns a random desktop UserAgent using weighted random selection
183183func (m * Manager ) GetRandomDesktop () (UserAgent , error ) {
184184 m .mu .RLock ()
185185 defer m .mu .RUnlock ()
186186
187- if len (m .desktopAgents ) == 0 {
188- return UserAgent {}, ErrEmptyAgentList
189- }
190-
191- idx , err := secureRandomInt (len (m .desktopAgents ))
192- if err != nil {
193- return UserAgent {}, fmt .Errorf ("failed to generate random index: %w" , err )
194- }
195-
196- return m .desktopAgents [idx ], nil
187+ return m .getWeightedRandomAgent (m .desktopAgents )
197188}
198189
199- // GetRandomMobile returns a random mobile UserAgent using crypto/rand
190+ // GetRandomMobile returns a random mobile UserAgent using weighted random selection
200191func (m * Manager ) GetRandomMobile () (UserAgent , error ) {
201192 m .mu .RLock ()
202193 defer m .mu .RUnlock ()
203194
204- if len (m .mobileAgents ) == 0 {
205- return UserAgent {}, ErrEmptyAgentList
206- }
207-
208- idx , err := secureRandomInt (len (m .mobileAgents ))
209- if err != nil {
210- return UserAgent {}, fmt .Errorf ("failed to generate random index: %w" , err )
211- }
212-
213- return m .mobileAgents [idx ], nil
195+ return m .getWeightedRandomAgent (m .mobileAgents )
214196}
215197
216198// GetRandomDesktopUA returns just the UA string of a random desktop user agent
@@ -236,20 +218,62 @@ func (m *Manager) GetRandomUA() (string, error) {
236218 m .mu .RLock ()
237219 defer m .mu .RUnlock ()
238220
221+ // Combine agents for weighted selection across all
222+ // Note: This assumes percentages in both files are relative to their own category (sum to ~100)
223+ // If we want to mix them, we might need to normalize or just treat them as one pool.
224+ // For simplicity and robustness, let's treat them as one big pool where weights are relative.
225+
239226 allAgents := make ([]UserAgent , 0 , len (m .desktopAgents )+ len (m .mobileAgents ))
240227 allAgents = append (allAgents , m .desktopAgents ... )
241228 allAgents = append (allAgents , m .mobileAgents ... )
242229
243- if len (allAgents ) == 0 {
244- return "" , ErrEmptyAgentList
230+ ua , err := m .getWeightedRandomAgent (allAgents )
231+ if err != nil {
232+ return "" , err
233+ }
234+ return ua .UA , nil
235+ }
236+
237+ // getWeightedRandomAgent selects an agent based on its Pct value
238+ func (m * Manager ) getWeightedRandomAgent (agents []UserAgent ) (UserAgent , error ) {
239+ if len (agents ) == 0 {
240+ return UserAgent {}, ErrEmptyAgentList
241+ }
242+
243+ var totalWeight float64
244+ for _ , ua := range agents {
245+ totalWeight += ua .Pct
245246 }
246247
247- idx , err := secureRandomInt (len (allAgents ))
248+ if totalWeight <= 0 {
249+ // Fallback to uniform selection if weights are invalid
250+ idx , err := secureRandomInt (len (agents ))
251+ if err != nil {
252+ return UserAgent {}, err
253+ }
254+ return agents [idx ], nil
255+ }
256+
257+ // Generate a random value in [0, totalWeight)
258+ // We use a large integer range for precision
259+ const precision = 1_000_000
260+ randInt , err := secureRandomInt (precision )
248261 if err != nil {
249- return "" , fmt .Errorf ("failed to generate random index: %w" , err )
262+ return UserAgent {}, fmt .Errorf ("failed to generate random value: %w" , err )
263+ }
264+
265+ randomWeight := float64 (randInt ) / float64 (precision ) * totalWeight
266+
267+ currentWeight := 0.0
268+ for _ , ua := range agents {
269+ currentWeight += ua .Pct
270+ if randomWeight < currentWeight {
271+ return ua , nil
272+ }
250273 }
251274
252- return allAgents [idx ].UA , nil
275+ // Should not happen if logic is correct, but return last one as fallback
276+ return agents [len (agents )- 1 ], nil
253277}
254278
255279// secureRandomInt generates a cryptographically secure random integer in [0, max)
0 commit comments