mirror of
https://github.com/idanoo/autobrr
synced 2025-07-22 08:19:12 +00:00
114 lines
2.5 KiB
Go
114 lines
2.5 KiB
Go
// Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors.
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
package client
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/autobrr/autobrr/pkg/errors"
|
|
|
|
"github.com/anacrolix/torrent/metainfo"
|
|
"github.com/avast/retry-go"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type DownloadFileResponse struct {
|
|
Body *io.ReadCloser
|
|
FileName string
|
|
}
|
|
|
|
type DownloadTorrentFileResponse struct {
|
|
MetaInfo *metainfo.MetaInfo
|
|
TmpFileName string
|
|
}
|
|
|
|
type HttpClient struct {
|
|
http *http.Client
|
|
}
|
|
|
|
func NewHttpClient() *HttpClient {
|
|
httpClient := &http.Client{
|
|
Timeout: time.Second * 10,
|
|
}
|
|
return &HttpClient{
|
|
http: httpClient,
|
|
}
|
|
}
|
|
|
|
func (c *HttpClient) DownloadTorrentFile(url string, opts map[string]string) (*DownloadTorrentFileResponse, error) {
|
|
if url == "" {
|
|
return nil, errors.New("download_file: url can't be empty")
|
|
}
|
|
|
|
// Create tmp file
|
|
tmpFile, err := os.CreateTemp("", "autobrr-")
|
|
if err != nil {
|
|
log.Error().Stack().Err(err).Msg("error creating temp file")
|
|
return nil, err
|
|
}
|
|
defer tmpFile.Close()
|
|
|
|
res := &DownloadTorrentFileResponse{}
|
|
// try request and if fail run 3 retries
|
|
err = retry.Do(func() error {
|
|
resp, err := http.Get(url)
|
|
if err != nil {
|
|
return errors.New("error downloading file: %q", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return errors.New("error downloading file bad status: %d", resp.StatusCode)
|
|
}
|
|
|
|
nuke := func() {
|
|
tmpFile.Seek(0, io.SeekStart)
|
|
tmpFile.Truncate(0)
|
|
}
|
|
|
|
// Write the body to file
|
|
_, err = io.Copy(tmpFile, resp.Body)
|
|
if err != nil {
|
|
nuke()
|
|
return errors.New("error writing downloaded file: %v | %q", tmpFile.Name(), err)
|
|
}
|
|
|
|
meta, err := metainfo.Load(resp.Body)
|
|
if err != nil {
|
|
nuke()
|
|
return errors.New("metainfo could not load file contents: %v | %q", tmpFile.Name(), err)
|
|
}
|
|
|
|
res = &DownloadTorrentFileResponse{
|
|
MetaInfo: meta,
|
|
TmpFileName: tmpFile.Name(),
|
|
}
|
|
|
|
if res.TmpFileName == "" || res.MetaInfo == nil {
|
|
nuke()
|
|
return errors.New("tmp file error - empty body")
|
|
}
|
|
|
|
if len(res.MetaInfo.InfoBytes) < 1 {
|
|
nuke()
|
|
return errors.New("could not read infohash")
|
|
}
|
|
|
|
log.Debug().Msgf("successfully downloaded file: %v", tmpFile.Name())
|
|
return nil
|
|
},
|
|
//retry.OnRetry(func(n uint, err error) { c.log.Printf("%q: attempt %d - %v\n", err, n, url) }),
|
|
retry.Delay(time.Second*5),
|
|
retry.Attempts(3),
|
|
retry.MaxJitter(time.Second*1))
|
|
|
|
if err != nil {
|
|
res = nil
|
|
}
|
|
|
|
return res, err
|
|
}
|