feat(clients): add support for qBittorrent 4.4.0+ (#558)

* refactor: move client to go-qbittorrent

* refactor: move client to go-qbittorrent

* feat(downloadclient): cache qbittorrent client

* feat(downloadclient): update qbit

* feat(downloadclient): client test and remove pkg qbit

* feat(downloadclient): update pkg qbit

* fix(release): method

* feat(release): make GetCachedClient concurrent safe

* feat(release): add additional tests for buildLegacyHost

* feat(release): remove branching

* chore: update pkg autobrr/go-qbittorrent to v.1.2.0
This commit is contained in:
ze0s 2022-12-10 19:25:04 +01:00 committed by GitHub
parent 6ad4abe296
commit 29da2416ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 379 additions and 1764 deletions

View file

@ -1,6 +1,12 @@
package domain
import "context"
import (
"context"
"fmt"
"net/url"
"github.com/autobrr/go-qbittorrent"
)
type DownloadClientRepo interface {
List(ctx context.Context) ([]DownloadClient, error)
@ -24,6 +30,11 @@ type DownloadClient struct {
Settings DownloadClientSettings `json:"settings,omitempty"`
}
type DownloadClientCached struct {
Dc *DownloadClient
Qbt *qbittorrent.Client
}
type DownloadClientSettings struct {
APIKey string `json:"apikey,omitempty"`
Basic BasicAuth `json:"basic,omitempty"`
@ -57,3 +68,48 @@ const (
DownloadClientTypeWhisparr DownloadClientType = "WHISPARR"
DownloadClientTypeReadarr DownloadClientType = "READARR"
)
func (c DownloadClient) BuildLegacyHost() string {
if c.Type == DownloadClientTypeQbittorrent {
return c.qbitBuildLegacyHost()
}
return ""
}
// qbitBuildLegacyHost exists to support older configs
func (c DownloadClient) qbitBuildLegacyHost() string {
// parse url
u, _ := url.Parse(c.Host)
// reset Opaque
u.Opaque = ""
// set scheme
scheme := "http"
if c.TLS {
scheme = "https"
}
u.Scheme = scheme
// if host is empty lets use one from settings
if u.Host == "" {
u.Host = c.Host
}
// reset Path
if u.Host == u.Path {
u.Path = ""
}
// handle ports
if c.Port > 0 {
if c.Port == 80 || c.Port == 443 {
// skip for regular http and https
} else {
u.Host = fmt.Sprintf("%v:%v", u.Host, c.Port)
}
}
// make into new string and return
return u.String()
}

View file

@ -0,0 +1,155 @@
package domain
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDownloadClient_qbitBuildLegacyHost(t *testing.T) {
type fields struct {
ID int
Name string
Type DownloadClientType
Enabled bool
Host string
Port int
TLS bool
TLSSkipVerify bool
Username string
Password string
Settings DownloadClientSettings
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "build_url_1",
fields: fields{
Host: "https://qbit.domain.ltd",
Port: 0,
Username: "",
Password: "",
TLS: true,
TLSSkipVerify: false,
},
want: "https://qbit.domain.ltd",
},
{
name: "build_url_2",
fields: fields{
Host: "http://qbit.domain.ltd",
Port: 0,
Username: "",
Password: "",
TLS: false,
TLSSkipVerify: false,
},
want: "http://qbit.domain.ltd",
},
{
name: "build_url_3",
fields: fields{
Host: "https://qbit.domain.ltd:8080",
Port: 0,
Username: "",
Password: "",
TLS: true,
TLSSkipVerify: false,
},
want: "https://qbit.domain.ltd:8080",
},
{
name: "build_url_4",
fields: fields{
Host: "qbit.domain.ltd:8080",
Port: 0,
Username: "",
Password: "",
TLS: false,
TLSSkipVerify: false,
},
want: "http://qbit.domain.ltd:8080",
},
{
name: "build_url_5",
fields: fields{
Host: "qbit.domain.ltd",
Port: 8080,
Username: "",
Password: "",
TLS: false,
TLSSkipVerify: false,
},
want: "http://qbit.domain.ltd:8080",
},
{
name: "build_url_6",
fields: fields{
Host: "qbit.domain.ltd",
Port: 443,
Username: "",
Password: "",
TLS: true,
TLSSkipVerify: false,
},
want: "https://qbit.domain.ltd",
},
{
name: "build_url_7",
fields: fields{
Host: "qbit.domain.ltd",
Port: 10200,
Username: "",
Password: "",
TLS: false,
TLSSkipVerify: false,
},
want: "http://qbit.domain.ltd:10200",
},
{
name: "build_url_8",
fields: fields{
Host: "https://domain.ltd/qbittorrent",
Port: 0,
Username: "",
Password: "",
TLS: true,
TLSSkipVerify: false,
},
want: "https://domain.ltd/qbittorrent",
},
{
name: "build_url_9",
fields: fields{
Host: "127.0.0.1",
Port: 8080,
Username: "",
Password: "",
TLS: false,
TLSSkipVerify: false,
},
want: "http://127.0.0.1:8080",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := DownloadClient{
ID: tt.fields.ID,
Name: tt.fields.Name,
Type: tt.fields.Type,
Enabled: tt.fields.Enabled,
Host: tt.fields.Host,
Port: tt.fields.Port,
TLS: tt.fields.TLS,
TLSSkipVerify: tt.fields.TLSSkipVerify,
Username: tt.fields.Username,
Password: tt.fields.Password,
Settings: tt.fields.Settings,
}
assert.Equalf(t, tt.want, c.qbitBuildLegacyHost(), "qbitBuildLegacyHost()")
})
}
}

View file

@ -273,7 +273,15 @@ func (r *Release) ParseSizeBytesString(size string) {
r.Size = s
}
func (r *Release) DownloadTorrentFileCtx(ctx context.Context) error {
return r.downloadTorrentFile(ctx)
}
func (r *Release) DownloadTorrentFile() error {
return r.downloadTorrentFile(context.Background())
}
func (r *Release) downloadTorrentFile(ctx context.Context) error {
if r.TorrentURL == "" {
return errors.New("download_file: url can't be empty")
} else if r.TorrentTmpFile != "" {
@ -294,7 +302,7 @@ func (r *Release) DownloadTorrentFile() error {
Timeout: time.Second * 45,
}
req, err := http.NewRequest(http.MethodGet, r.TorrentURL, nil)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, r.TorrentURL, nil)
if err != nil {
return errors.Wrap(err, "error downloading file")
}