package realdebrid import ( "math" "net/http" "strings" "time" ) func (rd *RealDebrid) UnrestrictUntilOk(link string) *UnrestrictResponse { if link == "" { return nil } unrestrictFn := func(link string) (*UnrestrictResponse, error) { return rd.UnrestrictLink(link) } return retryUntilOk(func() (*UnrestrictResponse, error) { return unrestrictFn(link) }) } func retryUntilOk[T any](fn func() (T, error)) T { const initialDelay = 1 * time.Second const maxDelay = 128 * time.Second for i := 0; ; i++ { result, err := fn() if err == nil || !strings.Contains(err.Error(), "429") { return result } delay := time.Duration(math.Min(float64(initialDelay*time.Duration(math.Pow(2, float64(i)))), float64(maxDelay))) time.Sleep(delay) } } func canFetchFirstByte(url string) bool { const maxAttempts = 3 for i := 0; i < maxAttempts; i++ { // Create a new HTTP request req, err := http.NewRequest("GET", url, nil) if err != nil { continue } // Set the Range header to request only the first byte req.Header.Set("Range", "bytes=0-0") // Execute the request resp, err := http.DefaultClient.Do(req) if err != nil { time.Sleep(1 * time.Second) // Add a delay before the next retry continue } defer resp.Body.Close() // If server supports partial content if resp.StatusCode == http.StatusPartialContent { buffer := make([]byte, 1) _, err := resp.Body.Read(buffer) if err == nil { return true } } else if resp.StatusCode == http.StatusOK { // If server doesn't support partial content, try reading the first byte and immediately close buffer := make([]byte, 1) _, err = resp.Body.Read(buffer) if err == nil { return true } } time.Sleep(1 * time.Second) // Add a delay before the next retry } return false }