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 = 2 * time.Second const maxDelay = 128 * time.Second const maxRetries = 5 // Maximum retries for non-429 errors var result T var err error var retryCount int for { result, err = fn() if err == nil { return result } // If error is 429, we retry indefinitely, hence no condition to break the loop. if !strings.Contains(err.Error(), "429") { retryCount++ if retryCount >= maxRetries { // If we've reached the maximum retries for errors other than 429, return the last result. return result } } // Calculate delay with exponential backoff delay := time.Duration(math.Min(float64(initialDelay)*math.Pow(2, float64(retryCount)), 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 }